ShiroConfiguration.java 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package com.yaozhitech.spring5.config;
  2. import java.util.Arrays;
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. import javax.servlet.DispatcherType;
  6. import javax.servlet.Filter;
  7. import org.apache.shiro.authc.Authenticator;
  8. import org.apache.shiro.authc.pam.FirstSuccessfulStrategy;
  9. import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
  10. import org.apache.shiro.authz.AuthorizationException;
  11. import org.apache.shiro.mgt.SecurityManager;
  12. import org.apache.shiro.mgt.SessionStorageEvaluator;
  13. import org.apache.shiro.realm.Realm;
  14. import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
  15. import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
  16. import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
  17. import org.apache.shiro.web.mgt.DefaultWebSessionStorageEvaluator;
  18. import org.springframework.beans.factory.annotation.Value;
  19. import org.springframework.boot.web.servlet.FilterRegistrationBean;
  20. import org.springframework.context.annotation.Bean;
  21. import org.springframework.context.annotation.Configuration;
  22. import org.springframework.http.HttpStatus;
  23. import org.springframework.ui.Model;
  24. import org.springframework.web.bind.annotation.ExceptionHandler;
  25. import org.springframework.web.bind.annotation.ResponseStatus;
  26. import com.yaozhitech.spring5.filter.AnyRolesAuthorizationFilter;
  27. import com.yaozhitech.spring5.filter.JwtAuthFilter;
  28. import com.yaozhitech.spring5.jwt.JWTShiroRealm;
  29. import com.yaozhitech.spring5.service.UserService;
  30. @Configuration
  31. public class ShiroConfiguration {
  32. @Value("${password.salt}")
  33. private String encryptSalt;
  34. /**
  35. * 注册shiro的Filter,拦截请求
  36. */
  37. @Bean
  38. public FilterRegistrationBean<Filter> filterRegistrationBean(SecurityManager securityManager,UserService userService) throws Exception{
  39. FilterRegistrationBean<Filter> filterRegistration = new FilterRegistrationBean<Filter>();
  40. filterRegistration.setFilter((Filter)shiroFilter(securityManager, userService).getObject());
  41. filterRegistration.addInitParameter("targetFilterLifecycle", "true");
  42. filterRegistration.setAsyncSupported(true);
  43. filterRegistration.setEnabled(true);
  44. filterRegistration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC);
  45. return filterRegistration;
  46. }
  47. @Bean
  48. public Authenticator authenticator(UserService userService) {
  49. ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
  50. authenticator.setRealms(Arrays.asList(jwtShiroRealm(userService)));
  51. authenticator.setAuthenticationStrategy(new FirstSuccessfulStrategy());
  52. return authenticator;
  53. }
  54. /**
  55. * 禁用session, 不保存用户登录状态。保证每次请求都重新认证。
  56. * 需要注意的是,如果用户代码里调用Subject.getSession()还是可以用session,如果要完全禁用,要配合下面的noSessionCreation的Filter来实现
  57. */
  58. @Bean
  59. protected SessionStorageEvaluator sessionStorageEvaluator(){
  60. DefaultWebSessionStorageEvaluator sessionStorageEvaluator = new DefaultWebSessionStorageEvaluator();
  61. sessionStorageEvaluator.setSessionStorageEnabled(false);
  62. return sessionStorageEvaluator;
  63. }
  64. /**
  65. * 用于JWT token认证的realm
  66. */
  67. @Bean("jwtRealm")
  68. public Realm jwtShiroRealm(UserService userService) {
  69. JWTShiroRealm myShiroRealm = new JWTShiroRealm(userService);
  70. return myShiroRealm;
  71. }
  72. /**
  73. * 设置过滤器,将自定义的Filter加入
  74. */
  75. @Bean("shiroFilter")
  76. public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager, UserService userService) {
  77. ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
  78. factoryBean.setSecurityManager(securityManager);
  79. Map<String, Filter> filterMap = factoryBean.getFilters();
  80. filterMap.put("authcToken", createAuthFilter(userService));
  81. // filterMap.put("anyRole", createRolesFilter());
  82. factoryBean.setFilters(filterMap);
  83. factoryBean.setFilterChainDefinitionMap(shiroFilterChainDefinition().getFilterChainMap());
  84. return factoryBean;
  85. }
  86. @Bean
  87. protected ShiroFilterChainDefinition shiroFilterChainDefinition() {
  88. DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
  89. // chainDefinition.addPathDefinition("/login", "noSessionCreation,anon"); //login不做认证,noSessionCreation的作用是用户在操作session时会抛异常
  90. // chainDefinition.addPathDefinition("/logout", "noSessionCreation,authcToken[permissive]"); //做用户认证,permissive参数的作用是当token无效时也允许请求访问,不会返回鉴权未通过的错误
  91. // chainDefinition.addPathDefinition("/image/**", "anon");
  92. // chainDefinition.addPathDefinition("/admin/**", "noSessionCreation,authcToken,anyRole[admin,manager]"); //只允许admin或manager角色的用户访问
  93. chainDefinition.addPathDefinition("/article/list", "noSessionCreation,authcToken");
  94. chainDefinition.addPathDefinition("/admin/**", "noSessionCreation,authcToken");
  95. // chainDefinition.addPathDefinition("/article/*", "noSessionCreation,authcToken[permissive]");
  96. chainDefinition.addPathDefinition("/**", "noSessionCreation,authcToken"); // 默认进行用户鉴权
  97. return chainDefinition;
  98. }
  99. //注意不要加@Bean注解,不然spring会自动注册成filter
  100. protected JwtAuthFilter createAuthFilter(UserService userService){
  101. return new JwtAuthFilter(userService);
  102. }
  103. // protected AnyRolesAuthorizationFilter createRolesFilter(){
  104. // return new AnyRolesAuthorizationFilter();
  105. // }
  106. @ExceptionHandler(AuthorizationException.class)
  107. @ResponseStatus(HttpStatus.FORBIDDEN)
  108. public String handleException(AuthorizationException e, Model model) {
  109. // you could return a 404 here instead (this is how github handles 403, so the user does NOT know there is a
  110. // resource at that location)
  111. // log.debug("AuthorizationException was thrown", e);
  112. Map<String, Object> map = new HashMap<String, Object>();
  113. map.put("status", HttpStatus.FORBIDDEN.value());
  114. map.put("message", "No message available");
  115. model.addAttribute("errors", map);
  116. return "error";
  117. }
  118. }