如何在Spring Boot项目中忽略特定URL的Spring Security CSRF

Pra*_*A.K 2 java csrf spring-security rest-client spring-boot

如何忽略特定URL的CSRF安全性,例如“ / workflow / **”。除了该URL,我还需要所有URL和方法的授权和CSRF安全。

@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private RESTAuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    private RESTAuthenticationFailureHandler authenticationFailureHandler;

    @Autowired
    private RESTAuthenticationSuccessHandler authenticationSuccessHandler;

    @Autowired
    private PranaUserDetailsService userDetailsService;

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

        http.csrf().requireCsrfProtectionMatcher(new AllExceptUrlStartedWith("/workflow"))          
        .and().authorizeRequests()
        .antMatchers("/rest/**", "/tasklist").authenticated()
        .and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
        .logoutSuccessUrl("/index.html")        
        .and().exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
        .and().formLogin().successHandler(authenticationSuccessHandler)
        .and().formLogin().failureHandler(authenticationFailureHandler)         
        .and().csrf().csrfTokenRepository(csrfTokenRepository()).and().addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
    }

    private static class AllExceptUrlStartedWith implements RequestMatcher {

        private static final String[] ALLOWED_METHODS =
                new String[] {"GET"};

        private final String[] allowedUrls;

        public AllExceptUrlStartedWith(String... allowedUrls) {
            this.allowedUrls = allowedUrls;
        }

        @Override
        public boolean matches(HttpServletRequest request) {
            String method = request.getMethod();
            for(String allowedMethod : ALLOWED_METHODS) {
                if (allowedMethod.equals(method)) {
                    return false;
                }
            }

            String uri = request.getRequestURI();
            for (String allowedUrl : allowedUrls) {
                if (uri.startsWith(allowedUrl)) {
                    return false;
                }
            }
            return true;
        }

    }

    private CsrfTokenRepository csrfTokenRepository() {
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
        repository.setHeaderName("X-XSRF-TOKEN");
        return repository;
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/styles/**").antMatchers("/scripts/**");
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }
}
Run Code Online (Sandbox Code Playgroud)

如何忽略特定URL的CSRF安全性,例如“ / workflow / **”。除了该URL,我还需要所有URL和方法的授权和CSRF安全。

Sla*_*hin 5

在我的项目中,我使用以下代码:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
        ...
        .csrf()
            // Allow unsecured requests to H2 console
            .requireCsrfProtectionMatcher(new AllExceptUrlsStartedWith("/console"))
        ...
}

private static class AllExceptUrlsStartedWith implements RequestMatcher {

        private static final String[] ALLOWED_METHODS =
            new String[] {"GET", "HEAD", "TRACE", "OPTIONS"};

        private final String[] allowedUrls;

        public AllExceptUrlsStartedWith(String... allowedUrls) {
            this.allowedUrls = allowedUrls;
        }

        @Override
        public boolean matches(HttpServletRequest request) {
            // replicate default behavior (see CsrfFilter.DefaultRequiresCsrfMatcher class)
            String method = request.getMethod();
            for (String allowedMethod : ALLOWED_METHODS) {
                if (allowedMethod.equals(method)) {
                    return false;
                }
            }

            // apply our own exceptions
            String uri = request.getRequestURI();
            for (String allowedUrl : allowedUrls) {
                if (uri.startsWith(allowedUrl)) {
                    return false;
                }
            }

            return true;
        }

    }
Run Code Online (Sandbox Code Playgroud)

在此示例中,我已禁用的CSRF保护/console


更新:从Spring Security 4.0开始,您可以将其简化为一行

csrf()
    .ignoringAntMatchers("/nocsrf","/ignore/startswith/**")
Run Code Online (Sandbox Code Playgroud)