Spring 启动 -- Post 使用 CSRF 令牌的请求产生 403 错误

Spring Boot -- Post request with CSRF token produce 403 error

我正在尝试在我的 Spring 启动 API 中实现 CSRF 令牌安全,以了解如何处理它。

我已关注 this tutorial (server side part),这是我的安全配置:

private static final String[] CSRF_IGNORE = {"/api/login"};


protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf()
                .ignoringAntMatchers(CSRF_IGNORE)
                .csrfTokenRepository(csrfTokenRepository())
                .and()
                .addFilterAfter(new CustomCsrfFilter(), CsrfFilter.class)
                .exceptionHandling()
                .authenticationEntryPoint(new Http403ForbiddenEntryPoint() {
                })
                .and()
                .authenticationProvider(getProvider())
                .formLogin()
                .loginProcessingUrl("/api/login")
                .successHandler(new AuthentificationLoginSuccessHandler())
                .failureHandler(new SimpleUrlAuthenticationFailureHandler())
                .and()
                .logout()
                .logoutUrl("/api/logout")
                .logoutSuccessHandler(new AuthentificationLogoutSuccessHandler())
                .invalidateHttpSession(true)
                .and()
                .authorizeRequests()
                .anyRequest().authenticated();
    }

其他与教程相同

我正在使用 Postman 进行测试。

当我在 CSRF_IGNORE 中添加我想要的端点时,我可以看到 logger/debug 存储的令牌和来自 cookie 的令牌是相同的,因为使用了 .addFilterAfter() 中的安全配置部分 CustomCsrfFilter.java,但是当我从此 CSRF_IGNORE,我得到的是 403,并且未使用 CustomCsrfFilter.java 中的 logger/debug,因此我认为未比较令牌。

我觉得我漏掉了什么,想了解一下

如果您想将 CSRF 与仅限 http 的假 cookie 一起使用,为什么不使用 Spring 内置的安全性 CookieCsrfTokenRepository?应该以这种方式简化您的配置。 CustomCsrfFilter 似乎正在向 HttpServletResponse 添加 XSRF-TOKEN cookie,CookieCsrfTokenRepository does for you

使用 CookieCsrfTokenRepository 时默认的 CSRF cookie 名称是 X-CSRF-TOKEN,这是 Angular 的 HttpClientXsrfModule 使用的默认名称。当然,如果需要,您可以自定义。

因此您的安全配置变为:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf()
                    .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                .and()
                .exceptionHandling()
                    .authenticationEntryPoint(new Http403ForbiddenEntryPoint())
                .and()
                    .authenticationProvider(getProvider())
                .formLogin()
                    .loginProcessingUrl("/api/login")
                    .successHandler(new AuthentificationLoginSuccessHandler())
                    .failureHandler(new SimpleUrlAuthenticationFailureHandler())
                .and()
                .logout()
                    .logoutUrl("/api/logout")
                    .logoutSuccessHandler(new AuthentificationLogoutSuccessHandler())
                    .invalidateHttpSession(true)
                .and()
                .authorizeRequests()
                    .anyRequest().authenticated();
    }

并且 Angular,您的应用程序模块 HttpClientXsrfModule 作为

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    HttpClientXsrfModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }