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

6tqwzwtp  于 5个月前  发布在  Spring
关注(0)|答案(4)|浏览(111)

我怎么能忽略CSRF安全的特定URL,如“/workflow/**"。除了这个URL,我需要授权和CSRF安全的所有URL的和方法。

@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());
    }
}

字符串
我怎么能忽略CSRF安全的特定URL,如“/workflow/**"。除了这个URL,我需要授权和CSRF安全的所有URL的和方法。

3yhwsihp

3yhwsihp1#

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

@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;
        }

    }

字符串
在本例中,我禁用了/console的CSRF保护。
更新:自Spring Security 4.0以来,您可以将其简化为一行:

csrf()
    .ignoringAntMatchers("/nocsrf","/ignore/startswith/**")

qyswt5oh

qyswt5oh2#

在这个线程中回答的唯一目的是解释和使用antPathMatcher,它的优点可以用来保护许多使用ant matchers的url。
从Doc

.csrf().requireCsrfProtectionMatcher(RequestMatcher requireCsrfProtectionMatcher)

指定RequestMatcher用于确定何时应用CSRF。默认值是忽略GET、HEAD、TRACE、OPTIONS并处理所有其他请求。
注意默认情况下GETHEADTRACEOPTIONS请求被忽略。如果你想覆盖这个默认配置requireCsrfProtectionMatcher(implementation_of_RequestMatcher)
在RequestMatcher的实现中,定义所有需要保护的URL。您完成了

假设您希望确保URL的/api/**用于CSRF保护

@Autowired
RequestMatcher csrfProtectedMatchers;

@Override
protected void configure(final HttpSecurity http) throws Exception
{
    http
        .authorizeRequests()
            .antMatchers("/resources/**", "/", "/login").permitAll()
            .antMatchers("/api/**").hasAnyRole("ADMIN", "USER")
            .antMatchers("/app/user/*")
                .hasAnyRole("ADMIN", "USER")
        .and().formLogin()
        .and().csrf().requireCsrfProtectionMatcher(csrfProtectedMatchers);
}

@Bean
public RequestMatcher getCsrfProtectedMatchers()
{
    UrlPathHelper urlPathHelper = new UrlPathHelper();
    AntPathMatcher antPathMatcher = new AntPathMatcher();

    List<String> protectedUrlPatterns = Arrays.asList("/api/**", "/logout");

    return new RequestMatcher()
    {
        @Override
        public boolean matches(HttpServletRequest request)
        {
            String uri = urlPathHelper.getPathWithinApplication(request);
            for (String pattern : protectedUrlPatterns)
            {
                if (antPathMatcher.match(pattern, uri))
                {
                    return true;
                }
            }
            return false;
        }
    };
}

字符串

逻辑解释

假设URL:http://localhost:8080/csrf/api/test1
String uri = urlPathHelper.getPathWithinApplication(request);
uri => /api/test1 ;
antPathMatcher.match("/api/**", "/api/test1") => true

byqmnocz

byqmnocz3#

回答我自己的问题.感谢@Slava

@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());
        }
    }

字符串

5sxhfpxr

5sxhfpxr4#

在Spring Security 6中,可以使用CsrfConfigurer#ignoringRequestMatchers
举例来说:

@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http.csrf(csrf -> csrf.ignoringRequestMatchers("/workflow/**"));
    return http.build();
}

字符串

相关问题