| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- package jnpf.config;
- import cn.dev33.satoken.annotation.handler.SaAnnotationHandlerInterface;
- import cn.dev33.satoken.context.SaHolder;
- import cn.dev33.satoken.interceptor.SaInterceptor;
- import cn.dev33.satoken.same.SaSameUtil;
- import cn.dev33.satoken.strategy.SaAnnotationStrategy;
- import cn.dev33.satoken.strategy.SaStrategy;
- import jnpf.annotation.SaCheckSame;
- import jnpf.base.UserInfo;
- import jnpf.consts.AuthConsts;
- import jnpf.filter.ClearThreadContextFilter;
- import jnpf.filter.RequestWrapperFilter;
- import jnpf.filter.SecurityFilter;
- import jnpf.handler.IRestHandler;
- import jnpf.encrypt.EncryptRestInterceptor;
- import jnpf.properties.SecurityProperties;
- import jnpf.util.StringUtil;
- import jnpf.util.UserProvider;
- import jnpf.util.context.SpringContext;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
- import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
- import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
- import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
- import jakarta.servlet.*;
- import java.lang.reflect.AnnotatedElement;
- import java.util.List;
- import java.util.function.BiFunction;
- /**
- *
- * @author JNPF开发平台组
- * @copyright 引迈信息技术有限公司
- */
- @Slf4j
- @Configuration
- @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
- public class SecurityConfiguration implements WebMvcConfigurer {
- @Autowired
- private SecurityProperties securityProperties;
- /**
- * 注册sa-token的拦截器
- */
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- initSaInterfaceAuth(registry);
- initEncryptRestInterceptor(registry);
- }
- /**
- * 请求封装过滤器
- */
- @Bean("myRequestWrapperFilter")
- @ConditionalOnMissingBean(name = "myRequestWrapperFilter")
- public Filter getRequestWrapperFilter(List<IRestHandler> handlers){
- return new RequestWrapperFilter(handlers, securityProperties);
- }
- /**
- * 线程变量清除过滤器
- */
- @Bean("myClearThreadContextFilter")
- @ConditionalOnMissingBean(name = "myClearThreadContextFilter")
- public Filter getClearThreadContextFilter(){
- return new ClearThreadContextFilter();
- }
- /**
- * 来源验证、用户、租户设置过滤器
- */
- @Bean("mySecurityFilter")
- @ConditionalOnMissingBean(name = "mySecurityFilter")
- public Filter getSecurityFilter(SecurityProperties securityProperties, ConfigValueUtil configValueUtil){
- return new SecurityFilter(securityProperties, configValueUtil).addInclude("/**");
- }
- /**
- * 传输加密
- */
- @Bean("myEncryptRestInterceptor")
- @ConditionalOnMissingBean(name = "myEncryptRestInterceptor")
- @ConditionalOnProperty(prefix = "security", name = "enable-rest-encrypt", havingValue = "true")
- public HandlerInterceptor getEncryptRestInterceptor(){
- return new EncryptRestInterceptor();
- }
- protected void initEncryptRestInterceptor(InterceptorRegistry registry){
- if(securityProperties.isEnableRestEncrypt()){
- registry.addInterceptor(SpringContext.getBean("myEncryptRestInterceptor"));
- }
- }
- protected void initSaInterfaceAuth(InterceptorRegistry registry){
- if(securityProperties.isEnablePreAuth()) {
- // 注册同源校验
- SaAnnotationStrategy.instance.registerAnnotationHandler(new SaAnnotationHandlerInterface<SaCheckSame>() {
- @Override
- public Class<SaCheckSame> getHandlerAnnotationClass() {
- return SaCheckSame.class;
- }
- @Override
- public void checkMethod(SaCheckSame at, AnnotatedElement element) {
- SaSameUtil.checkToken(SaHolder.getRequest().getHeader(AuthConsts.INNER_TOKEN_KEY));
- }
- });
- // 开启接口请求权限控制
- registry.addInterceptor(new SaInterceptor().isAnnotation(securityProperties.isEnablePreAuth())).addPathPatterns("/**");
- }
- //接口鉴权忽略管理员、内部请求
- BiFunction<List<String>, String, Boolean> oldCheckFunc = SaStrategy.instance.hasElement;
- SaStrategy.instance.hasElement = (list, element) -> {
- //启用之后才验证
- if (securityProperties.isEnablePreAuth()) {
- UserInfo userInfo = UserProvider.getUser();
- //未获取到用户信息返回false
- if (StringUtil.isEmpty(userInfo.getUserId())) {
- return false;
- }
- //管理员返回true
- if (userInfo.getIsAdministrator()) {
- return true;
- }
- boolean result = oldCheckFunc.apply(list, element);
- //如果鉴权失败, 检测是否来自内部请求
- if (!result) {
- String innerToken = SaHolder.getRequest().getHeader(AuthConsts.INNER_TOKEN_KEY);
- //来自内部请求(非网关) 无需鉴权
- if (UserProvider.isValidInnerToken(innerToken)) {
- result = true;
- }
- }
- return result;
- }
- return true;
- };
- }
- }
|