我将我的项目升级到Spring 3和SpringSecurity6,但是升级后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);
});在Spring 2.7.x中,此设置工作良好,但如果我将项目升级到Spring 3和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的更改有关。但是,我不明白我必须更改代码的内容,或者是否需要异或某些内容。
我确实检查了它是否是由于CSRF令牌的新延迟加载所致,但即使我再次单击该按钮(并验证XSRF-令牌cookie是否已设置),它仍然无法工作。
发布于 2022-11-21 15:37:38
最近,我在参考文档中添加了一节,用于迁移到5.8 (准备迁移到6.0),演示了解决这个问题的方法。
TL;博士见我正在使用AngularJS或其他Javascript框架。
这里的问题是AngularJS (以及上面的示例代码)直接使用XSRF-TOKEN cookie。在Security 6之前,这是很好的。但不幸的是,cookie实际上用于持久化原始令牌,而对于Security 6,默认情况下不接受原始令牌。理想情况下,前端框架将能够使用另一个源来获取令牌,例如X-XSRF-TOKEN响应头。
但是,即使使用Security 6,这样的响应头也不会被开箱即出,尽管它可能是一个值得推荐的增强。我还没有建议进行这样的增强,因为Javascript框架在默认情况下无法使用它。
现在,您需要通过配置Security 6以接受原始令牌来解决这个问题,正如上面链接的第一节所建议的那样。该建议允许提交原始令牌,但继续使用XorCsrfTokenRequestAttributeHandler提供请求属性的散列版本(例如,request.getAttribute(CsrfToken.class.getName())或request.getAttribute("_csrf")),以防任何东西将CSRF令牌呈现给可能容易被破坏的HTML。
我建议找一个可靠的来源来更彻底地研究违规行为,但不幸的是,我不能声称自己是这样一个消息来源。
我还建议现在关注Security问题,因为一旦社区开始使用Security 6,情况可能会很快发生变化。您可以使用这个过滤器作为跟踪与CSRF相关的问题的一种可能方式。
发布于 2022-11-18 20:26:54
谢谢你这么做!在JHipster + Spring 3应用程序中,我能够使用它解决类似的项目。然而,这个类名似乎最近可能发生了变化。我要用的是:
.csrf(csrf -> csrf
.csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse())
.csrfTokenRequestHandler(new ServerCsrfTokenRequestAttributeHandler()))发布于 2022-11-16 07:01:53
目前,我通过禁用XorCsrfTokenRequestAttributeHandler来解决这个问题,如下所示:
.csrf(csrf -> csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
// Added this:
.csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler()))然而,这意味着我很可能很容易受到攻击。
https://stackoverflow.com/questions/74447118
复制相似问题