spring security 过滤器优化

This commit is contained in:
海言
2025-09-09 17:47:57 +08:00
parent aca39614d1
commit 96e1f6727f
6 changed files with 54 additions and 210 deletions

View File

@@ -1,51 +0,0 @@
//package cn.xf.basedemo.config;
//
//import cn.xf.basedemo.interceptor.CustomAccessDeniedHandler;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
//import org.springframework.boot.web.servlet.FilterRegistrationBean;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.security.config.Customizer;
//import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
//import org.springframework.security.config.annotation.web.builders.HttpSecurity;
//import org.springframework.security.web.SecurityFilterChain;
//import org.springframework.web.cors.CorsConfiguration;
//import org.springframework.web.cors.CorsConfigurationSource;
//import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
//import org.springframework.web.filter.CorsFilter;
//
///**
// * Description: 全局跨域配置
// *
// */
//@Slf4j
//@Configuration
//@EnableMethodSecurity(prePostEnabled = true) // 开启 @PreAuthorize/@PostAuthorize
//public class GlobalCorsConfig {
//
// @ConditionalOnMissingBean
// @Bean
// public FilterRegistrationBean<CorsFilter> corsFilter() {
// CorsConfiguration config = new CorsConfiguration();
// // 放行哪些原始域
// //config.addAllowedOrigin("*");
// // 放行哪些原始域,SpringBoot2.4.4下低版本使用.allowedOrigins("*")
// config.addAllowedOriginPattern("*");
// // 放行哪些原始请求头部信息
// config.addAllowedHeader("*");
// // 放行全部请求
// config.addAllowedMethod("*");
// // 是否发送Cookie
// config.setAllowCredentials(true);
//
// UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
// configSource.registerCorsConfiguration("/**", config);
//
// FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(configSource));
// // 这个顺序很重要哦,为避免麻烦请设置在最前
// bean.setOrder(0);
// return bean;
// }
//
//}

View File

@@ -1,48 +0,0 @@
package cn.xf.basedemo.config.security;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
/**
* Description: spring security体系 全局跨域配置
*/
@Slf4j
@Configuration
@EnableMethodSecurity(prePostEnabled = true) // 开启 @PreAuthorize/@PostAuthorize
public class SpringSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors(Customizer.withDefaults()) // 开启 CORS
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/**", "/web/**").permitAll() // 放行登录、注册接口
.anyRequest().authenticated()
);
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
}

View File

@@ -1,43 +0,0 @@
package cn.xf.basedemo.interceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @program: spring-boot-base-demo
* @ClassName InterceptorConfig
* @description:
* @author: xiongfeng
* @create: 2022-06-16 13:59
**/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Bean
public TokenInterceptor tokenInterceptor() {
return new TokenInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(tokenInterceptor()) //登录逻辑拦截类
.addPathPatterns("/**") //需要拦截的请求(设置的全部拦截)
.excludePathPatterns("/user/login", "/web/**"); //忽略的请求
}
/**
* 放行Knife4j请求
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}

View File

@@ -0,0 +1,50 @@
package cn.xf.basedemo.interceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
/**
* Description: spring security体系 全局跨域配置
*/
@Slf4j
@Configuration
@EnableMethodSecurity(prePostEnabled = true) // 开启 @PreAuthorize/@PostAuthorize
public class SpringSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http,
TokenAuthenticationFilter tokenAuthenticationFilter) throws Exception {
http
.cors(Customizer.withDefaults()) // 开启 CORS
.csrf(AbstractHttpConfigurer::disable) //前后端分离 禁用csrf
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
) // 把自定义过滤器插入 Spring Security 过滤器链
.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
}

View File

@@ -89,7 +89,10 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"message\":\"" + e.getMessage() + "\"}");
}
}finally {
// 无论请求是否异常,最后一定清理,避免 ThreadLocal 泄漏
SessionContext.getInstance().clear();
}
}
// Authentication auth = SecurityContextHolder.getContext().getAuthentication();
// CustomUserDetails user = (CustomUserDetails) auth.getPrincipal();

View File

@@ -1,67 +0,0 @@
package cn.xf.basedemo.interceptor;
import ch.qos.logback.core.LayoutBase;
import cn.xf.basedemo.common.exception.LoginException;
import cn.xf.basedemo.common.exception.ResponseCode;
import cn.xf.basedemo.common.model.CustomUserDetails;
import cn.xf.basedemo.common.model.LoginUser;
import cn.xf.basedemo.common.utils.ApplicationContextUtils;
import cn.xf.basedemo.mappers.SysPermissionMapper;
import cn.xf.basedemo.mappers.SysRoleMapper;
import com.alibaba.fastjson.JSONObject;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.UserDetailsManagerConfigurer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* @program: spring-boot-base-demo
* @ClassName TokenInterceptor
* @description: 拦截器职责(日志、请求校验、限流)
* @author: xiongfeng
* @create: 2022-06-16 14:17
**/
@Component
public class TokenInterceptor implements HandlerInterceptor {
//不拦截的请求列表
private static final List<String> EXCLUDE_PATH_LIST = Arrays.asList("/user/login", "/web/login", "/swagger-ui.html", "/v3/api-docs", "/swagger-ui/index.html");
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
if (EXCLUDE_PATH_LIST.contains(requestURI) ||
requestURI.contains("/swagger-ui") ||
requestURI.contains("/v3/api-docs")) {
return true;
}
return HandlerInterceptor.super.preHandle(request, response, handler);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
SessionContext.getInstance().clear();
}
}