spring security下开启csrf,同时支持session.invalidate()调用

在Java Web项目中,配置Spring Security启用CSRF防御时,遇到HTTPS与HTTP切换导致的session问题。当用户身份验证成功并跳转到HTTP时,由于session变化,新的session缺少CSRF Token引发403错误。解决方案是在验证成功后的跳转action中更新session。此外,为应对session ID更新需求,可能需要修改Spring Security源码,确保在filterChain执行后重新添加CSRF Token到session。

最近在做的一个java web项目,要求登录界面信息提交时使用https,登录成功后页面使用http,同时全站使用csrf防御。

然后https和http的访问会分别创建两个session,csrf的token存在于https创建的session中,当验证用户身份通过后,跳转到http进入时,新建的session中没有csrfToken,因此被403拒绝访问。

解决方法为:在身份验证成功后,跳转页面的action中加入

Cookie nck = new Cookie("JSESSIONID",request.getSession().getId());
			nck.setPath("/");
			nck.setSecure(true);
			response.addCookie(nck);
这样就可以保证跳转前后的session保持一致了。


但新的需求又来了:在某些action处理过程中,需要更新session id,可以参考《spring security 集成csrf与会话更新》,也可以修改spring security源码。

spring security的CsrfFilter.java文件中,在filterChain执行完回调后,再添加一次token到session中即可:

@Override
	protected void doFilterInternal(HttpServletRequest request,
			HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {
		
		
<think>我们之前提到Spring Security默认的过滤器链中包含了`UsernamePasswordAuthenticationFilter`,但在你提供的列表中却没有出现,而是出现了`JwtAuthenticationFilter`(一个自定义过滤器)。原因如下: ### 原因分析: 1. **自定义配置覆盖了默认行为**: - 当你在项目中添加了自定义的安全配置(例如继承`WebSecurityConfigurerAdapter`或使用`@EnableWebSecurity`的配置类)时,可能会覆盖Spring Security的默认配置。 - 默认情况下,如果启用了表单登录(`formLogin()`),则`UsernamePasswordAuthenticationFilter`会被添加到过滤器链中。但如果你禁用了表单登录,或者配置了其他认证方式(如JWT),则该过滤器不会被添加。 2. **JWT认证替代了表单登录**: - 从你打印的过滤器列表中可以看到有一个`org.example.security.JwtAuthenticationFilter`(自定义的JWT过滤器),这通常用于处理基于Token的认证。 - 当使用JWT等自定义认证方式时,开发者通常会**禁用表单登录**(不调用`formLogin()`方法),因此`UsernamePasswordAuthenticationFilter`不会被激活。 3. **其他可能原因**: - 如果配置了HTTP Basic认证(`httpBasic()`),则会添加`BasicAuthenticationFilter`,但不会添加`UsernamePasswordAuthenticationFilter`。 - 如果配置了其他认证机制(如OAuth2、LDAP等),也会改变默认的过滤器链。 ### 验证方法: 检查你的安全配置类(通常命名为`SecurityConfig`),查看是否包含以下情况: ```java @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http // 如果禁用了表单登录,就不会有UsernamePasswordAuthenticationFilter .formLogin().disable() // 或者根本没有调用formLogin() .addFilter(new JwtAuthenticationFilter(authenticationManager())) // 添加了自定义JWT过滤器 ... // 其他配置 } } ``` ### 解决方案: 如果你希望同时保留表单登录和JWT认证(例如同时支持浏览器和API请求),可以显式启用表单登录并调整过滤器的顺序: ```java http .formLogin() // 启用表单登录(会添加UsernamePasswordAuthenticationFilter) .and() .addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); // 在表单登录前添加JWT过滤器 ``` ### 总结: **没有`UsernamePasswordAuthenticationFilter`是因为你的配置中禁用了表单登录(或未启用),而使用了自定义的JWT认证过滤器替代了默认的用户名密码认证流程。** §§相关问题§§ 1. 如何在Spring Security同时启用表单登录和JWT认证? 2. 自定义过滤器(如JwtAuthenticationFilter)应该放在Spring Security过滤器链的哪个位置? 3. 禁用Spring Security的表单登录后,如何自定义登录接口? 4. 为什么在Spring Security中自定义过滤器时需要关注过滤器的顺序? 5. 除了UsernamePasswordAuthenticationFilter,Spring Security还有哪些内置的认证过滤器?</think>### 为什么没有 `UsernamePasswordAuthenticationFilter`? 在您列出的过滤器链中,没有出现 `UsernamePasswordAuthenticationFilter` 的原因通常有以下几点: #### 1. **自定义安全配置覆盖了默认行为** - 当您在 `SecurityConfig` 类中自定义了安全配置(如使用 `@EnableWebSecurity`),**默认的表单登录会被禁用** - 例如以下配置会移除表单登录相关的过滤器: ```java @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .anyRequest().authenticated() .and() // 没有启用 formLogin() .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class); } ``` #### 2. **使用了 JWT 认证替代表单登录** - 您的过滤器链中包含自定义的 `org.example.security.JwtAuthenticationFilter` - 这通常表示您**用 JWT 认证替代了默认的表单登录机制** - `UsernamePasswordAuthenticationFilter` 是专用于处理表单登录(`/login` 端点)的,当您使用 JWT 时它会被移除 #### 3. **特定配置禁用了表单登录** - 如果您在配置中显式禁用了表单登录: ```java http.formLogin().disable(); // 明确关闭表单登录 ``` - 这会直接移除 `UsernamePasswordAuthenticationFilter` 和相关的 `DefaultLoginPageGeneratingFilter` #### 4. **认证机制的选择** - 当您配置了其他认证方式时(如 HTTP Basic 认证),Spring Security 会**自动调整过滤器链**: ```java http.httpBasic(); // 启用HTTP Basic认证 → 添加BasicAuthenticationFilter ``` - 此时 `UsernamePasswordAuthenticationFilter` 会被 `BasicAuthenticationFilter` 替代 ### 验证方法: 1. **检查安全配置类** 查看是否调用了 `formLogin()` 方法。如果没有调用调用了 `formLogin().disable()`,则不会生成该过滤器。 2. **查看自定义过滤器的位置** 您的 `JwtAuthenticationFilter` 很可能被配置在 `UsernamePasswordAuthenticationFilter` 的位置: ```java http.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class); ``` 这种配置会用 JWT 过滤器完全替代表单登录过滤器。 ### 总结: **`UsernamePasswordAuthenticationFilter` 缺失是因为您使用了 JWT 认证方案,覆盖了 Spring Security 的默认表单登录行为。这是自定义安全配置时的正常现象,表明您的认证流程已转向基于 Token 的机制。**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值