SpringSecurity过滤器顺序

本文深入解析Spring Security框架中的关键过滤器及其工作流程,包括默认过滤器的启动顺序、自定义过滤器的实现方法,以及各过滤器如ChannelProcessingFilter、SecurityContextPersistenceFilter、HeaderWriterFilter的功能与配置细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

官网地址 

官网定义的关键过滤器顺序:

 

源码里所有的过滤器顺序:

 

默认情况会启动以下过滤器:

(默认设置在:WebSecurityConfigurerAdapter 的  getHttp()方法里)

 

怎么替换默认的过滤器: 

http.addFilterAt() 不能替换默认的过滤器,只是在相同的位置放置一个过滤器,原本的过滤器仍然起作用

可以disable掉默认的过滤器,例如用自定义的登出过滤器

http.logout().disable();

http.addFilterAt(new MyLogoutFilter(), LogoutFilter.class);

 

部分过滤器的含义:

ChannelProcessingFilter:转换协议时使用,例如将http重定向到https

 

ConcurrentSessionFilter:判断session是否过期以及更新最新访问时间

 

SecurityContextPersistenceFilter:将用户信息绑定到线程

这样全局可通过SecurityContextHolder.getContext().getAuthentication()拿到用户信息

注:如果要拿到request/response信息(这个不是过滤器设置的,是框架默认会绑定到线程)

可通过((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest()

 

HeaderWriterFilter:默认增加以下头部信息

X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY

关闭:http.headers().disable();

只保留缓存控制:http.headers().defaultsDisabled().cacheControl()

注:详细描述可查看官网地址

X-Content-Type-Options: nosniff 表示浏览器必须且只能根据Content-Type字段分辨资源类型(浏览器默认会 猜测资源类型)

X-XSS-Protection:防范XSS攻击

  • 0:禁用XSS保护;
  • 1:启用XSS保护;
  • 1; mode=block:启用XSS保护,并在检查到XSS攻击时,停止渲染页面(例如IE8中,检查到攻击时,整个页面会被一个#替换);

X-Frame-Options:是否允许页面被嵌套

DENY  表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许
SAMEORIGIN  表示该页面可以在相同域名页面的 frame 中展示
ALLOW-FROM uri  表示该页面可以在指定来源的 frame 中展示

Cache-Control/Pragma/Expires:缓存控制(简单描述

 

CorsFilter: 配置跨域

@Override
	protected void configure(HttpSecurity http) throws Exception {
		http
			// by default uses a Bean by the name of corsConfigurationSource
			.cors().and()
			...
	}

	@Bean
	CorsConfigurationSource corsConfigurationSource() {
		CorsConfiguration configuration = new CorsConfiguration();
		configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
		configuration.setAllowedMethods(Arrays.asList("GET","POST"));
		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
		source.registerCorsConfiguration("/**", configuration);
		return source;
	}

 

CsrfFilter: 防止Csrf攻击,通过配置与Session绑定的token,每次请求都需要携带最新的token

注:默认是在前后端不分离的情况下,通过jsp/ft等传递到前端。在前后端分离的情况下,可以增加过滤器使其配置在 json/或者头部

 

LogoutFilter配置登出的处理 一般可设置登出成功的处理,删除cookie,使Session无效等

 

 

UsernamePasswordAuthenticationFilter:验证登录,并可以配置登录成功/失败的处理

                http.formLogin() // 表单登录
                // 登录的界面,前后端分离时不需要这个配置。没登录去访问系统资源时会重定向到这个界面
                .loginPage("/login/home")
                // 登录验证,框架自动实现
                .loginProcessingUrl("/login/verify")
                //  如果直接访问的是登录界面login1,返回的URL,否则会返回重定向到原本请求的URL
                .successHandler(myAuthenticationSuccessHandler)
                //  失败返回的URL
                .failureHandler(myAuthenticationFailureHandler)

 

SecurityContextHolderAwareRequestFilter: 包装类,实现HttpServletRequest的getAuthentication getRemoteUser等方法

 

RememberMeAuthenticationFilter: 配置rememberMe,比如7天之内不需要登录

当拿不到用户信息时(SecurityContextHolder.getContext()为空),会去找key是remember-me的Cookie配置用户信息

 

AnonymousAuthenticationFilter:没有通过username和remember认证的用户赋予匿名身份

 

SessionManagementFilter:session管理:限制同一用户开启多个会话的数量

 

ExceptionTranslationFilter:一般其只处理两大类异常:

AccessDeniedException访问权限异常

AuthenticationException用户认证异常:包括匿名用户异常

配置自定义的401和403异常处理:

 http.exceptionHandling()
                .accessDeniedHandler(new MyAccessDeniedHandler())
                .authenticationEntryPoint(new MyAuthenticationEntryPoint());

 

FilterSecurityInterceptor :拿到用户的权限(从SecurityContextHolder中获取Authentication对象)和资源所需权限(SecurityMetadataSource),在AccessDecisionManager里对比看用户是否有权限

 

 

注:

CsrfFilter类

@Override
	protected void doFilterInternal(HttpServletRequest request,
			HttpServletResponse response, FilterChain filterChain)
					throws ServletException, IOException {
		request.setAttribute(HttpServletResponse.class.getName(), response);
        // 获取与session绑定的csrfToken,没有就新建一个
		CsrfToken csrfToken = this.tokenRepository.loadToken(request);
		final boolean missingToken = csrfToken == null;
		if (missingToken) {
			csrfToken = this.tokenRepository.generateToken(request);
			this.tokenRepository.saveToken(csrfToken, request, response);
		}
        
		request.setAttribute(CsrfToken.class.getName(), csrfToken);
		request.setAttribute(csrfToken.getParameterName(), csrfToken);
        
        // 如果不是与csrf相关的请求就直接跳过
		if (!this.requireCsrfProtectionMatcher.matches(request)) {
			filterChain.doFilter(request, response);
			return;
		}
        // 否则直接比对 头部/表单里的csrfToken 和 session绑定的CsrfToken
		String actualToken = request.getHeader(csrfToken.getHeaderName());
		if (actualToken == null) {
			actualToken = request.getParameter(csrfToken.getParameterName());
		}
		if (!csrfToken.getToken().equals(actualToken)) {
			if (this.logger.isDebugEnabled()) {
				this.logger.debug("Invalid CSRF token found for "
						+ UrlUtils.buildFullRequestUrl(request));
			}
			if (missingToken) {
				this.accessDeniedHandler.handle(request, response,
						new MissingCsrfTokenException(actualToken));
			}
			else {
				this.accessDeniedHandler.handle(request, response,
						new InvalidCsrfTokenException(csrfToken, actualToken));
			}
			return;
		}

		filterChain.doFilter(request, response);
	}

 

 

 

 

### Spring Security 过滤器链中的各个过滤器执行顺序 在Spring Security框架内,多个过滤器按照预定义的顺序排列并依次调用以完成一系列的安全控制任务。这些过滤器被设计成能够处理诸如身份验证、访问权限检查等功能,并且每一个都有独特的角色。 #### 默认情况下,Spring Security 的过滤器链通常遵循如下顺序: 1. **WebAsyncManagerIntegrationFilter** 此过滤器用于支持异步请求下的安全上下文传播[^2]。 2. **SecurityContextPersistenceFilter** 负责保存和恢复`SecurityContextHolder`中的`SecurityContext`对象,在每次HTTP请求开始时初始化安全上下文,并在结束时清理它。 3. **HeaderWriterFilter** 添加必要的响应头来增强安全性,比如防止点击劫持(X-Frame-Options),设置缓存策略(Cache-Control)等。 4. **CsrfFilter** 实现跨站请求伪造保护机制,通过比较客户端提交的CSRF令牌与服务器端存储的一致性来进行防护。 5. **LogoutFilter** 处理用户的登出逻辑,当接收到匹配路径的POST请求时触发注销过程。 6. **UsernamePasswordAuthenticationFilter** 验证基于用户名/密码的身份凭证,默认绑定到/login URL上。 7. **DefaultLoginPageGeneratingFilter & DefaultLogoutPageGeneratingFilter** 当未提供自定义登录页面或退出页面时自动创建默认版本。 8. **ConcurrentSessionFilter** 控制同一用户的同时在线会话数量,超出限额则拒绝新连接。 9. **OAuth2LoginAuthenticationFilter, Saml2WebSsoAuthenticationFilter**, etc. 支持多种第三方认证方式如OAuth2/SAML SSO协议。 10. **RequestCacheAwareFilter** 如果之前存在重定向,则尝试从缓存中检索原始请求信息以便继续处理。 11. **SecurityContextHolderAwareRequestWrapperFilter** 将当前线程关联的安全上下文封装进HttpServletRequest对象中供后续使用。 12. **RememberMeAuthenticationFilter** 对于启用了记住我的服务,此过滤器会在成功登录后向浏览器发送持久化Cookie。 13. **AnonymousAuthenticationFilter** 若无其他形式的有效认证,则为匿名用户提供临时身份标识。 14. **SessionManagementFilter** 管理会话固定攻击风险以及强制单一会话等问题。 15. **ExceptionTranslationFilter** 捕获所有抛出自定义异常(如AccessDeniedException),并将它们转换成适当类型的HTTP错误状态码返回给客户端;同时也会处理来自下游过滤器未能解决的身份验证需求[^3]。 16. **FilterSecurityInterceptor (FSI)** 作为最后一个核心组件,负责实际执行资源级别的授权决策,即判断已认证主体是否有权访问指定URL模式所代表的目标资源。 以上就是典型的Spring Security过滤器链条路及其工作次序描述。值得注意的是,开发者可以根据项目具体需求调整这个列表内的成员构成及位置关系,甚至添加额外定制化的过滤单元。 为了配置上述提到的各种过滤器,可以利用Java Config 或 XML命名空间的方式进行声明式编程。对于大多数现代应用程序而言,推荐采用前者——借助@EnableWebSecurity注解配合SecurityConfig类内部的方法注入实现灵活而强大的安全设定。 ```java @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") // 定义受保护资源规则 .anyRequest().authenticated() // 其他任何请求都需要经过身份验证 .and() .formLogin(); // 开启表单登陆功能 } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值