CSRF保护不适用于Spring Security 6

watbbzwu  于 2022-11-24  发布在  Spring
关注(0)|答案(3)|浏览(476)

我将我的项目升级到了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),它仍然不起作用。

jobtbby3

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相关问题的一种可能的方法。

u3r8eeie

u3r8eeie2#

感谢这个!我可以用它来解决JHipster + Sping Boot 3应用程序中的一个类似项目。但是,似乎类名最近可能发生了变化。下面是我不得不使用的:

.csrf(csrf -> csrf
    .csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse())
    .csrfTokenRequestHandler(new ServerCsrfTokenRequestAttributeHandler()))
neskvpey

neskvpey3#

我目前通过禁用XorCsrfTokenRequestAttributeHandler来解决这个问题,如下所示:

.csrf(csrf -> csrf
    .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
    // Added this:
    .csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler()))

但是,这意味着我很可能容易受到BREACH攻击。

相关问题