我将我的项目升级到了Sping Boot 3和Spring Security 6,但是自从升级以来,CSRF保护不再起作用。
我正在使用以下配置:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated())
.httpBasic(withDefaults())
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS))
.csrf(csrf -> csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))
.build();
}
@Bean
public UserDetailsService userDetailsService() {
UserDetails user = User.builder().username("user").password("{noop}test").authorities("user").build();
return new InMemoryUserDetailsManager(user);
}
在我的网页上,只有一个按钮:
<button id="test">Test CSRF</button>
以及以下JavaScript代码:
document.querySelector("#test").addEventListener('click', async function() {
console.log('Clicked');
// This code reads the cookie from the browser
// Source: https://stackoverflow.com/a/25490531
const csrfToken = document.cookie.match('(^|;)\\s*XSRF-TOKEN\\s*=\\s*([^;]+)')?.pop();
const result = await fetch('./api/foo', {
method: 'POST',
headers: {
'X-XSRF-Token': csrfToken
}
});
console.log(result);
});
在Sping Boot 2.7.x中,此设置工作正常,但如果我将项目升级到Spring Boot 3和Spring Security 6,则会出现403错误,并显示以下调试日志:
15:10:51.858 D o.s.security.web.csrf.CsrfFilter: Invalid CSRF token found for http://localhost:8080/api/foo
15:10:51.859 D o.s.s.w.access.AccessDeniedHandlerImpl: Responding with 403 status code
我的猜测是这与#4001的改变有关。但是我不明白我必须改变我的代码或者我是否必须XOR一些东西。
我确实检查了这是否是由于CSRF令牌的新延迟加载,但即使我第二次单击该按钮(并验证是否设置了XSRF-TOKEN cookie),它仍然不起作用。
3条答案
按热度按时间jobtbby31#
我最近在迁移到5.8(为6.0做准备)的参考文档中添加了一节,演示了此问题的解决方案。
**TLDR;**请参阅我正在使用AngularJS或其他Javascript框架。
这里的问题是AngularJS(以及上面的示例代码)直接使用
XSRF-TOKEN
cookie。在SpringSecurity 6之前,这是可以的。但不幸的是,cookie实际上用于持久化原始令牌,而在SpringSecurity 6中,默认情况下不接受原始令牌。理想情况下,前端框架将能够使用另一个源来获取令牌,例如X1 M1 N1 X响应报头。然而,即使在Spring Security 6中,这种响应头也不是现成的,尽管它可能是一个值得建议的增强。我还没有建议这样的增强,因为Javascript框架在默认情况下不能使用它。
现在,您需要通过配置SpringSecurity 6来接受原始令牌来解决这个问题,正如我在上面链接的部分中所建议的那样。(例如
request.getAttribute(CsrfToken.class.getName())
或request.getAttribute("_csrf")
),以防任何内容将CSRF令牌呈现为易受BREACH攻击的HTML响应。我会建议找到一个有信誉的来源,研究突破更彻底,但不幸的是,我不能声称是这样的来源。
我还建议您现在关注Spring Security问题,因为一旦社区开始使用Spring Security 6,情况可能会很快发生变化。您可以使用this filter作为跟踪CSRF相关问题的一种可能的方法。
u3r8eeie2#
感谢这个!我可以用它来解决JHipster + Sping Boot 3应用程序中的一个类似项目。但是,似乎类名最近可能发生了变化。下面是我不得不使用的:
neskvpey3#
我目前通过禁用
XorCsrfTokenRequestAttributeHandler
来解决这个问题,如下所示:但是,这意味着我很可能容易受到BREACH攻击。