X-CSRF-TOKEN 不是 Spring Boot 生成的

Posted

技术标签:

【中文标题】X-CSRF-TOKEN 不是 Spring Boot 生成的【英文标题】:X-CSRF-TOKEN is not generated by Spring Boot 【发布时间】:2016-07-15 16:18:11 【问题描述】:

我按照这里的指南:http://spring.io/guides/gs/rest-service/ 构建了我的休息服务示例,现在我正在尝试启用 CSRF 保护。我读到它应该默认启用,所以如果我不包括:

http.csrf().disable()

在我的WebSecurityConfigurerAdapter 配置中,CSRF 保护应默认启用,但似乎并非如此。问题是 X-CSRF-TOKEN 没有生成,也没有以任何方式包含在我的 HTTP 响应中。 我应该做什么来生成 x-csrf-token 并将其包含在响应中,当然还有 csrf 保护完全工作?

我注意到,使用类似的 spring mvc 配置,我得到了生成的 x-csrf-token,简单地包括:

在我的安全配置文件中。但是,使用 Spring Boot 时,我可能会遇到问题,并且无法生成 csrf 令牌。任何人都可以帮助我,也许指向我一个工作的例子?我的安全配置是:

     @Override
     protected void configure(HttpSecurity http) throws Exception 
     
        http
      // .csrf().disable()
      .authorizeRequests()
          .anyRequest()
          .authenticated()
      .and()
      .httpBasic()
      .authenticationEntryPoint(new RestAuthenticationEntryPoint())
      .and()
      .formLogin()
      .successHandler(new RestAuthenticationSuccessHandler())
      .failureHandler(new SimpleUrlAuthenticationFailureHandler())
      .and()
      .logout()
      .logoutSuccessHandler(new RestLogoutSuccessHandler());


@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception 

    auth.userDetailsService(restUserDetailService);

【问题讨论】:

提供有问题的spring安全配置java代码 感谢 Kunal,在上面添加了我的 configure() 方法。 你如何调用你的休息服务? 如果您只创建非浏览器客户端使用的服务,您可能希望禁用 CSRF 保护。检查when to use csrf 最后解决了我对spring security csrf-protection for rest services这篇文章的问题,希望对像我一样与spring战斗的其他人有用! 【参考方案1】:

我们在安全测试中遇到了非常相似的问题,我们怀疑我们不小心在 websecurityconfig 类的 configure 方法中禁用了 csfr,默认情况下它是启用的。通过如下所示更改配置方法,我们让spring自动生成csfr令牌。

websecurityconfig 类配置方法==>

@Override
protected void configure(HttpSecurity http) throws Exception               

     http
     .authorizeRequests()
         .antMatchers("/", "/login","/loginError","/home","/interruption").permitAll()                                                          
         .antMatchers("/admin").hasAuthority(Roles.ROLE_PREFIX.role()+Roles.HALLEYYNT01.role())  
         .antMatchers("/requests").hasAuthority(Roles.ROLE_PREFIX.role()+Roles.CCHALLEYLOGIN.role())
         .antMatchers("/solrequests").hasAuthority(Roles.ROLE_PREFIX.role()+Roles.SOLHALLEYLOGIN.role())
         .anyRequest().authenticated()
         .and()
     .formLogin()             
         .loginPage("/login")  
         //.failureUrl("/loginError")
         .loginProcessingUrl("/authenticate")
         .defaultSuccessUrl("/")            
         .and()
     .logout().clearAuthentication(true).invalidateHttpSession(true).deleteCookies("JSESSIONID")         
         .logoutSuccessUrl("/login");
         //.and() 
     //.exceptionHandling().accessDeniedHandler(accessDeniedHandler);    
   

【讨论】:

【参考方案2】:

要将 CSRF Token 包含在您的 csrf 保护中,您可以包含 CSRFTokenRepository 以生成令牌。为了说明您的情况,添加一条简单的线就足够了:

 @Override
 protected void configure(HttpSecurity http) throws Exception 
 
  http.
  .csrf()
  .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) //HERE !  Defaults XSRF-TOKEN as cookie name and X-XSRF-TOKEN as header name  
  .authorizeRequests()
  .anyRequest()
  .authenticated()
  .and()
  .httpBasic()
  .authenticationEntryPoint(new RestAuthenticationEntryPoint())
  .and()
  .formLogin()
  .successHandler(new RestAuthenticationSuccessHandler())
  .failureHandler(new SimpleUrlAuthenticationFailureHandler())
  .and()
  .logout()
  .logoutSuccessHandler(new RestLogoutSuccessHandler());

【讨论】:

【参考方案3】:

使用 Spring security 5.3.0.Final,生成 CSRF 令牌的方法之一是使用以下代码在 cookie 中进行设置。

 http.csrf(csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))

您还需要在请求中包含生成的 CSRF 令牌以供服务器授权。

<form>
    <input type="hidden" name="_csrf" value="$cookie['XSRF-TOKEN'].getValue()" />
    //Code goes here
</form>

如果您使用的是 JS 框架,则需要通过在请求标头中设置令牌来包含令牌。

这是一个 JQuery ajax 调用示例。

// Get the CSRF token from the cookie
const csrfCookie= document.cookie.replace(/(?:(?:^|.*;\s*)XSRF-TOKEN\s*\=\s*([^;]*).*$)|^.*$/, '$1');
// Add the CSRF token to each ajax request header
settings.beforeSend = function(xhr) 
  xhr.setRequestHeader('X-XSRF-TOKEN', springCsrfCookie);
;
$.ajax(settings);

Spring 在此处记录了其他满足您需求的实现。 https://docs.spring.io/spring-security/site/docs/5.3.0.RELEASE/reference/html5/#servlet-csrf

【讨论】:

【参考方案4】:

您可以配置CookieCsrfTokenRepository。 使用 Java 配置将 CSRF 令牌存储在 Cookie 中

    @Override
    protected void configure(HttpSecurity http) 
        http
            .csrf(csrf ->
                csrf
                    .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            );
    

【讨论】:

以上是关于X-CSRF-TOKEN 不是 Spring Boot 生成的的主要内容,如果未能解决你的问题,请参考以下文章

easy-rules-centraldogma-spring-boot-starter 引入外部rule

404-not-found-while-running-spring-boot-rest-api

自定义spring-boot-autocofigure使用maven打包的时候报错了:Failed to execute goal org.springframework.boot:spring-bo

CSRF 和 X-CSRF-Token 的区别

使用 Spring-Boot 创建一个简单的 JAR 而不是可执行的 JAR

在 laravel+vuejs 项目中允许 X-CSRF-TOKEN 吗?