¿我怎样才能为我的api禁用CSRF弹簧安全?

ran*_*all 2 spring spring-security spring-tool-suite spring-boot

我用弹簧安全创建一个项目,但我只有我的api问题(所有控制器都与csrf正常工作).但似乎csrf给我的api造成了问题,因为当我向我的api提出请求时,我得到:

{"id":41,"titulo":"vineta3","creationdate":1489421003000,"URL":"http://i2.kym-cdn.com/photos/images/facebook/000/125/918/RMUBQ.png","likes":0,"dislikes":0,"descripcion":"des3"}{"timestamp":1489421218765,"status":200,"error":"OK","exception":"java.lang.IllegalStateException","message":"Cannot create a session after the response has been committed","path":"/api/vineta/41/"}
Run Code Online (Sandbox Code Playgroud)

最后信息:

{"timestamp":1489421218765,"status":200,"error":"OK","exception":"java.lang.IllegalStateException","message":"Cannot create a session after the response has been committed","path":"/api/vineta/41/"}
Run Code Online (Sandbox Code Playgroud)

当我的项目没有弹簧安全时,我没有回来.我使用下一个代码进行安全配置.

public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Autowired
public UserRepositoryAuthenticationProvider authenticationProvider;

@Override
protected void configure(HttpSecurity http) throws Exception {

    // Public pages
    http.authorizeRequests().antMatchers("/").permitAll();
    http.authorizeRequests().antMatchers("/login").permitAll();
    http.authorizeRequests().antMatchers("/loginerror").permitAll();
    http.authorizeRequests().antMatchers("/registro").permitAll();
    http.authorizeRequests().antMatchers("/signup").permitAll();
    http.authorizeRequests().antMatchers(HttpMethod.GET, "/api/**").permitAll();        


    // Private pages (all other pages)
    http.authorizeRequests().antMatchers("/home").hasAnyRole("USER");
    //http.authorizeRequests().antMatchers("/crearComentario/vineta/{id}").hasAnyRole("USER");

    // Login form
    http.formLogin().loginPage("/login");
    http.formLogin().usernameParameter("username");
    http.formLogin().passwordParameter("password");
    http.formLogin().defaultSuccessUrl("/home");
    http.formLogin().failureUrl("/loginerror");

    // Logout
    http.logout().logoutUrl("/logout");
    http.logout().logoutSuccessUrl("/");

}

@Override
protected void configure(AuthenticationManagerBuilder auth)
        throws Exception {
    // Database authentication provider
    auth.authenticationProvider(authenticationProvider);
}
Run Code Online (Sandbox Code Playgroud)

}

我的csrf的下一个:

@Configuration
public class CSRFHandlerConfiguration extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CSRFHandlerInterceptor());
    }
}

class CSRFHandlerInterceptor extends HandlerInterceptorAdapter {

    @Override
    public void postHandle(final HttpServletRequest request,
            final HttpServletResponse response, final Object handler,
            final ModelAndView modelAndView) throws Exception {

        CsrfToken token = (CsrfToken) request.getAttribute("_csrf"); 
        modelAndView.addObject("token", token.getToken());      
    }
}
Run Code Online (Sandbox Code Playgroud)

在控制台中,我可以看到以下日志:at

org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.0.32.jar:8.0.32]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_25]
Caused by: java.lang.IllegalStateException: Cannot create a session after the response has been committed
    at org.apache.catalina.connector.Request.doGetSession(Request.java:2928) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
Run Code Online (Sandbox Code Playgroud)

我没有使用SingleTransactionsController,这可能是问题吗?

cha*_*luo 7

我不明白你使用的原因CSRFHandlerInterceptor,但是如果你只想为API禁用CRSF,我有两个解决方案:

  1. 您可以requireCsrfProtectionMatcher向CSRF过滤器注入一个,例如:

     http
         .csrf()
             .requireCsrfProtectionMatcher(newAndRequestMatcher(CsrfFilter.DEFAULT_CSRF_MATCHER, new RegexRequestMatcher("^(?!/api/)", null)));
    
    Run Code Online (Sandbox Code Playgroud)

    默认匹配器是方法匹配器,第二个匹配器用于 /api/请求.

  2. 您可以仅为/api默认Spring Security配置创建新的Spring Security配置,并在没有CSRF的情况下匹配API URL:

    http.requestMatcher(new AntPathRequestMatcher("/api/**")).csrf().disable();
    
    Run Code Online (Sandbox Code Playgroud)


小智 7

启用 API 和 Web 安全性的另一种方法是将其包含在您的 SecurityConfig 类中:

@Override
protected void configure(HttpSecurity http) throws Exception {
            http
            .authorizeRequests()
            .antMatchers(....)
            //form login etc
            .and().csrf().ignoringAntMatchers("/api/**");
  }
Run Code Online (Sandbox Code Playgroud)