ShiroConfig.kt 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. package com.gxzc.zen.umps.config
  2. import com.gxzc.zen.umps.constant.ZenHttpSession
  3. import com.gxzc.zen.umps.filter.AjaxAuthorizationFilter
  4. import com.gxzc.zen.umps.filter.UrlPermissionsFilter
  5. import com.gxzc.zen.umps.filter.ZenCorsAnonymousFilter
  6. import com.gxzc.zen.umps.filter.ZenCorsPathMatchingFilter
  7. import org.apache.shiro.authc.credential.HashedCredentialsMatcher
  8. import org.apache.shiro.spring.LifecycleBeanPostProcessor
  9. import org.apache.shiro.spring.web.ShiroFilterFactoryBean
  10. import org.apache.shiro.web.filter.authc.AnonymousFilter
  11. import org.apache.shiro.web.mgt.DefaultWebSecurityManager
  12. import org.apache.shiro.web.servlet.SimpleCookie
  13. import org.springframework.boot.context.properties.ConfigurationProperties
  14. import org.springframework.boot.web.servlet.FilterRegistrationBean
  15. import org.springframework.context.annotation.Bean
  16. import org.springframework.context.annotation.Configuration
  17. import org.springframework.context.annotation.DependsOn
  18. import org.springframework.core.annotation.Order
  19. import org.springframework.data.redis.connection.jedis.JedisConnectionFactory
  20. import org.springframework.data.redis.core.RedisTemplate
  21. import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer
  22. import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer
  23. import org.springframework.data.redis.serializer.StringRedisSerializer
  24. import org.springframework.web.filter.DelegatingFilterProxy
  25. import javax.servlet.DispatcherType
  26. import javax.servlet.Filter
  27. /**
  28. * Shiro配置
  29. * @author NorthLan
  30. * @date 2018/4/21
  31. * @url https://noahlan.com
  32. */
  33. @Configuration
  34. class ShiroConfig {
  35. @Bean
  36. @ConfigurationProperties(prefix = "shiro.redis")
  37. fun shiroRedisProperties(): ShiroRedisProperties {
  38. return ShiroRedisProperties()
  39. }
  40. @Bean("shiroFilterRegistrationBean")
  41. @DependsOn("shiroFilter")
  42. fun filterRegistrationBean(): FilterRegistrationBean<DelegatingFilterProxy> {
  43. return FilterRegistrationBean<DelegatingFilterProxy>().apply {
  44. filter = DelegatingFilterProxy("shiroFilter")
  45. isEnabled = true
  46. addUrlPatterns("/*")
  47. setDispatcherTypes(DispatcherType.REQUEST)
  48. }
  49. }
  50. @Bean(name = ["shiroFilter"])
  51. @Order(2)
  52. fun shiroFilter(): ShiroFilterFactoryBean {
  53. return ShiroFilterFactoryBean().apply {
  54. securityManager = securityManager()
  55. // loginUrl = "/login"
  56. // unauthorizedUrl = "/unauthor"
  57. filters = hashMapOf<String, Filter>(
  58. "canon" to ZenCorsAnonymousFilter(),
  59. "cors" to ZenCorsPathMatchingFilter(),
  60. "perms" to UrlPermissionsFilter(),
  61. "authc" to AjaxAuthorizationFilter(),
  62. "anon" to AnonymousFilter()
  63. )
  64. /**
  65. * anon(匿名) org.apache.shiro.web.filter.authc.AnonymousFilter
  66. * authc(身份验证) org.apache.shiro.web.filter.authc.FormAuthenticationFilter
  67. * authcBasic(http基本验证) org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
  68. * logout(退出) org.apache.shiro.web.filter.authc.LogoutFilter
  69. * noSessionCreation(不创建session) org.apache.shiro.web.filter.session.NoSessionCreationFilter
  70. * perms(许可验证) org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
  71. * port(端口验证) org.apache.shiro.web.filter.authz.PortFilter
  72. * rest (rest方面) org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
  73. * roles(权限验证) org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
  74. * ssl (ssl方面) org.apache.shiro.web.filter.authz.SslFilter
  75. * member (用户方面) org.apache.shiro.web.filter.authc.UserFilter
  76. * user 表示用户不一定已通过认证,只要曾被Shiro记住过登录状态的用户就可以正常发起请求,比如rememberMe
  77. */
  78. filterChainDefinitionMap = linkedMapOf<String, String>( // BUG 此处一定要使用 linkedHashMap 否则顺序有问题
  79. "/auth/setcookie" to "canon", // 设置cookie
  80. "/auth/check" to "canon", // 检查登录状态
  81. "/auth/logout" to "canon", // 登出
  82. "/test/**" to "canon", // 测试 免登录
  83. "/upload/**" to "canon", // 上传免登录
  84. "/fdfsupload/**" to "canon", // 上传免登录
  85. "/api/**" to "canon", // api 免登陆
  86. "/ws/**" to "canon", // websocket 免登陆
  87. "/" to "canon",
  88. ////////////////////// 静态资源 /////////////////////
  89. "/v2/api-docs" to "canon",
  90. "/swagger-resources/**" to "anon",
  91. "/swagger-ui.html" to "anon",
  92. "/webjars*" to "anon",
  93. "/webjars/**" to "anon",
  94. "/druid/**" to "anon",
  95. "/druid/sql.json" to "anon",
  96. "/**/favicon.*" to "anon",
  97. "/eureka/**" to "anon",
  98. ////////////////////// 静态资源 /////////////////////
  99. "/**" to "cors,authc,perms" // 对于其他未配置的所有url 先设置cors头 再进行登陆判定 最后判定权限
  100. )
  101. }
  102. }
  103. @Bean(name = ["securityManager"])
  104. fun securityManager(): DefaultWebSecurityManager {
  105. return DefaultWebSecurityManager().apply {
  106. setRealm(userRealm())
  107. cacheManager = redisCacheManager()
  108. sessionManager = defaultWebSessionManager()
  109. }
  110. }
  111. @Bean(name = ["sessionManager"])
  112. fun defaultWebSessionManager(): ZenWebSessionManager {
  113. return ZenWebSessionManager().apply {
  114. setCacheManager(redisCacheManager())
  115. globalSessionTimeout = 604800 * 1000
  116. isDeleteInvalidSessions = true
  117. isSessionValidationSchedulerEnabled = true
  118. isDeleteInvalidSessions = true
  119. sessionDAO = redisSessionDAO()
  120. sessionIdCookie = SimpleCookie(ZenHttpSession.DEFAULT_SESSION_ID_NAME).apply {
  121. isHttpOnly = true
  122. maxAge = 604800
  123. }
  124. }
  125. }
  126. @Bean
  127. fun redisSessionDAO(): ShiroRedisSessionDAO {
  128. return ShiroRedisSessionDAO(redisTemplate(), shiroRedisProperties())
  129. }
  130. @Bean
  131. @DependsOn(value = ["shiroLifecycleBeanPostProcessor", "shrioRedisCacheManager"])
  132. fun userRealm(): ZenShiroRealm {
  133. return ZenShiroRealm().apply {
  134. cacheManager = redisCacheManager()
  135. isCachingEnabled = true
  136. isAuthenticationCachingEnabled = true
  137. isAuthorizationCachingEnabled = true
  138. //TODO 以下 hash 验证,后期的重试 ban 可重写此类实现
  139. credentialsMatcher = HashedCredentialsMatcher().also {
  140. it.hashAlgorithmName = "md5"
  141. it.hashIterations = 2 // 两次md5
  142. }
  143. }
  144. }
  145. @Bean(name = ["shrioRedisCacheManager"])
  146. @DependsOn(value = ["shiroRedisTemplate"])
  147. fun redisCacheManager(): ShiroRedisCacheManager {
  148. return ShiroRedisCacheManager(redisTemplate(), shiroRedisProperties())
  149. }
  150. @Bean(name = ["shiroRedisTemplate"])
  151. fun redisTemplate(): RedisTemplate<String, Any> {
  152. return RedisTemplate<String, Any>().apply {
  153. connectionFactory = connectionFactory()
  154. val stringSerializer = StringRedisSerializer()
  155. keySerializer = stringSerializer
  156. valueSerializer = JdkSerializationRedisSerializer()
  157. hashKeySerializer = stringSerializer
  158. hashValueSerializer = Jackson2JsonRedisSerializer(Any::class.java)
  159. }
  160. }
  161. @Bean("shiroRedisConnectionFactory")
  162. fun connectionFactory(): JedisConnectionFactory {
  163. val properties = shiroRedisProperties()
  164. return JedisConnectionFactory().apply {
  165. database = properties.database
  166. hostName = properties.host
  167. password = properties.password
  168. port = properties.port
  169. timeout = properties.timeout
  170. }
  171. }
  172. @Bean("shiroLifecycleBeanPostProcessor")
  173. fun lifecycleBeanPostProcessor(): LifecycleBeanPostProcessor {
  174. return LifecycleBeanPostProcessor()
  175. }
  176. }