SecurityConfiguration.java 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. package jnpf.config;
  2. import cn.dev33.satoken.annotation.handler.SaAnnotationHandlerInterface;
  3. import cn.dev33.satoken.context.SaHolder;
  4. import cn.dev33.satoken.interceptor.SaInterceptor;
  5. import cn.dev33.satoken.same.SaSameUtil;
  6. import cn.dev33.satoken.strategy.SaAnnotationStrategy;
  7. import cn.dev33.satoken.strategy.SaStrategy;
  8. import jnpf.annotation.SaCheckSame;
  9. import jnpf.base.UserInfo;
  10. import jnpf.consts.AuthConsts;
  11. import jnpf.filter.ClearThreadContextFilter;
  12. import jnpf.filter.RequestWrapperFilter;
  13. import jnpf.filter.SecurityFilter;
  14. import jnpf.handler.IRestHandler;
  15. import jnpf.encrypt.EncryptRestInterceptor;
  16. import jnpf.properties.SecurityProperties;
  17. import jnpf.util.StringUtil;
  18. import jnpf.util.UserProvider;
  19. import jnpf.util.context.SpringContext;
  20. import lombok.extern.slf4j.Slf4j;
  21. import org.springframework.beans.factory.annotation.Autowired;
  22. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
  23. import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  24. import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
  25. import org.springframework.context.annotation.Bean;
  26. import org.springframework.context.annotation.Configuration;
  27. import org.springframework.web.servlet.HandlerInterceptor;
  28. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  29. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  30. import jakarta.servlet.*;
  31. import java.lang.reflect.AnnotatedElement;
  32. import java.util.List;
  33. import java.util.function.BiFunction;
  34. /**
  35. *
  36. * @author JNPF开发平台组
  37. * @copyright 引迈信息技术有限公司
  38. */
  39. @Slf4j
  40. @Configuration
  41. @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
  42. public class SecurityConfiguration implements WebMvcConfigurer {
  43. @Autowired
  44. private SecurityProperties securityProperties;
  45. /**
  46. * 注册sa-token的拦截器
  47. */
  48. @Override
  49. public void addInterceptors(InterceptorRegistry registry) {
  50. initSaInterfaceAuth(registry);
  51. initEncryptRestInterceptor(registry);
  52. }
  53. /**
  54. * 请求封装过滤器
  55. */
  56. @Bean("myRequestWrapperFilter")
  57. @ConditionalOnMissingBean(name = "myRequestWrapperFilter")
  58. public Filter getRequestWrapperFilter(List<IRestHandler> handlers){
  59. return new RequestWrapperFilter(handlers, securityProperties);
  60. }
  61. /**
  62. * 线程变量清除过滤器
  63. */
  64. @Bean("myClearThreadContextFilter")
  65. @ConditionalOnMissingBean(name = "myClearThreadContextFilter")
  66. public Filter getClearThreadContextFilter(){
  67. return new ClearThreadContextFilter();
  68. }
  69. /**
  70. * 来源验证、用户、租户设置过滤器
  71. */
  72. @Bean("mySecurityFilter")
  73. @ConditionalOnMissingBean(name = "mySecurityFilter")
  74. public Filter getSecurityFilter(SecurityProperties securityProperties, ConfigValueUtil configValueUtil){
  75. return new SecurityFilter(securityProperties, configValueUtil).addInclude("/**");
  76. }
  77. /**
  78. * 传输加密
  79. */
  80. @Bean("myEncryptRestInterceptor")
  81. @ConditionalOnMissingBean(name = "myEncryptRestInterceptor")
  82. @ConditionalOnProperty(prefix = "security", name = "enable-rest-encrypt", havingValue = "true")
  83. public HandlerInterceptor getEncryptRestInterceptor(){
  84. return new EncryptRestInterceptor();
  85. }
  86. protected void initEncryptRestInterceptor(InterceptorRegistry registry){
  87. if(securityProperties.isEnableRestEncrypt()){
  88. registry.addInterceptor(SpringContext.getBean("myEncryptRestInterceptor"));
  89. }
  90. }
  91. protected void initSaInterfaceAuth(InterceptorRegistry registry){
  92. if(securityProperties.isEnablePreAuth()) {
  93. // 注册同源校验
  94. SaAnnotationStrategy.instance.registerAnnotationHandler(new SaAnnotationHandlerInterface<SaCheckSame>() {
  95. @Override
  96. public Class<SaCheckSame> getHandlerAnnotationClass() {
  97. return SaCheckSame.class;
  98. }
  99. @Override
  100. public void checkMethod(SaCheckSame at, AnnotatedElement element) {
  101. SaSameUtil.checkToken(SaHolder.getRequest().getHeader(AuthConsts.INNER_TOKEN_KEY));
  102. }
  103. });
  104. // 开启接口请求权限控制
  105. registry.addInterceptor(new SaInterceptor().isAnnotation(securityProperties.isEnablePreAuth())).addPathPatterns("/**");
  106. }
  107. //接口鉴权忽略管理员、内部请求
  108. BiFunction<List<String>, String, Boolean> oldCheckFunc = SaStrategy.instance.hasElement;
  109. SaStrategy.instance.hasElement = (list, element) -> {
  110. //启用之后才验证
  111. if (securityProperties.isEnablePreAuth()) {
  112. UserInfo userInfo = UserProvider.getUser();
  113. //未获取到用户信息返回false
  114. if (StringUtil.isEmpty(userInfo.getUserId())) {
  115. return false;
  116. }
  117. //管理员返回true
  118. if (userInfo.getIsAdministrator()) {
  119. return true;
  120. }
  121. boolean result = oldCheckFunc.apply(list, element);
  122. //如果鉴权失败, 检测是否来自内部请求
  123. if (!result) {
  124. String innerToken = SaHolder.getRequest().getHeader(AuthConsts.INNER_TOKEN_KEY);
  125. //来自内部请求(非网关) 无需鉴权
  126. if (UserProvider.isValidInnerToken(innerToken)) {
  127. result = true;
  128. }
  129. }
  130. return result;
  131. }
  132. return true;
  133. };
  134. }
  135. }