在 Spring Boot 中禁用特定 URL 模式的 CSRF 保护

问题描述 投票:0回答:4

我使用 Spring Boot 和 Spring Security 来创建我的 Web 项目。我想禁用特定 URL 模式的 CSRF 保护,以便为 Android 设备提供 API。

使用

我写了以下配置:

package com.hnu.tutorial.configs; import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.web.util.matcher.RegexRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import javax.servlet.http.HttpServletRequest; import java.util.regex.Pattern; @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { CsrfSecurityRequestMatcher crm = new CsrfSecurityRequestMatcher(); http.csrf().requireCsrfProtectionMatcher(crm).and() .authorizeRequests().antMatchers("/**").permitAll().anyRequest().fullyAuthenticated(); // http.csrf().disable(); } public class CsrfSecurityRequestMatcher implements RequestMatcher { private Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$"); private RegexRequestMatcher unprotectedMatcher = new RegexRequestMatcher("/api/**", null); @Override public boolean matches(HttpServletRequest request) { if(allowedMethods.matcher(request.getMethod()).matches()){ return false; } return !unprotectedMatcher.matches(request); } } }

当我运行该项目时,出现以下错误:

2016-08-08 09:29:27.172 ERROR 6715 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Exception starting filter springSecurityFilterChain org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.util.regex.PatternSyntaxException: Dangling meta character '*' near index 6 /api/** ^ at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1060) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE] at org.springframework.web.filter.DelegatingFilterProxy.initDelegate(DelegatingFilterProxy.java:326) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE] at org.springframework.web.filter.DelegatingFilterProxy.initFilterBean(DelegatingFilterProxy.java:235) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE] at org.springframework.web.filter.GenericFilterBean.init(GenericFilterBean.java:199) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE] at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:279) ~[tomcat-embed-core-8.0.33.jar:8.0.33] at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:109) ~[tomcat-embed-core-8.0.33.jar:8.0.33] at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4658) [tomcat-embed-core-8.0.33.jar:8.0.33] at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5277) [tomcat-embed-core-8.0.33.jar:8.0.33] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147) [tomcat-embed-core-8.0.33.jar:8.0.33] at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408) [tomcat-embed-core-8.0.33.jar:8.0.33] at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398) [tomcat-embed-core-8.0.33.jar:8.0.33] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_73] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_73] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_73] at java.lang.Thread.run(Thread.java:745) [na:1.8.0_73] Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.util.regex.PatternSyntaxException: Dangling meta character '*' near index 6 /api/** ^ at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] ... 23 common frames omitted Caused by: java.util.regex.PatternSyntaxException: Dangling meta character '*' near index 6 /api/** ^ at java.util.regex.Pattern.error(Pattern.java:1955) ~[na:1.8.0_73] at java.util.regex.Pattern.sequence(Pattern.java:2123) ~[na:1.8.0_73] at java.util.regex.Pattern.expr(Pattern.java:1996) ~[na:1.8.0_73] at java.util.regex.Pattern.compile(Pattern.java:1696) ~[na:1.8.0_73] at java.util.regex.Pattern.<init>(Pattern.java:1351) ~[na:1.8.0_73] at java.util.regex.Pattern.compile(Pattern.java:1028) ~[na:1.8.0_73] at org.springframework.security.web.util.matcher.RegexRequestMatcher.<init>(RegexRequestMatcher.java:68) ~[spring-security-web-4.0.4.RELEASE.jar:4.0.4.RELEASE] at org.springframework.security.web.util.matcher.RegexRequestMatcher.<init>(RegexRequestMatcher.java:52) ~[spring-security-web-4.0.4.RELEASE.jar:4.0.4.RELEASE] at com.hnu.tutorial.configs.SecurityConfig$CsrfSecurityRequestMatcher.<init>(SecurityConfig.java:35) ~[classes/:na] at com.hnu.tutorial.configs.SecurityConfig.configure(SecurityConfig.java:27) ~[classes/:na] at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.getHttp(WebSecurityConfigurerAdapter.java:199) ~[spring-security-config-4.0.4.RELEASE.jar:4.0.4.RELEASE] at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.init(WebSecurityConfigurerAdapter.java:290) ~[spring-security-config-4.0.4.RELEASE.jar:4.0.4.RELEASE] at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.init(WebSecurityConfigurerAdapter.java:67) ~[spring-security-config-4.0.4.RELEASE.jar:4.0.4.RELEASE] at com.hnu.tutorial.configs.SecurityConfig$$EnhancerBySpringCGLIB$$db9c0de0.init(<generated>) ~[classes/:na] at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.init(AbstractConfiguredSecurityBuilder.java:370) ~[spring-security-config-4.0.4.RELEASE.jar:4.0.4.RELEASE] at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.doBuild(AbstractConfiguredSecurityBuilder.java:324) ~[spring-security-config-4.0.4.RELEASE.jar:4.0.4.RELEASE] at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:41) ~[spring-security-config-4.0.4.RELEASE.jar:4.0.4.RELEASE] at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration.springSecurityFilterChain(WebSecurityConfiguration.java:105) ~[spring-security-config-4.0.4.RELEASE.jar:4.0.4.RELEASE] at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$5dd0484b.CGLIB$springSecurityFilterChain$4(<generated>) ~[spring-security-config-4.0.4.RELEASE.jar:4.0.4.RELEASE] at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$5dd0484b$$FastClassBySpringCGLIB$$a796ba38.invoke(<generated>) ~[spring-security-config-4.0.4.RELEASE.jar:4.0.4.RELEASE] at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) ~[spring-core-4.2.6.RELEASE.jar:4.2.6.RELEASE] at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:356) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE] at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$5dd0484b.springSecurityFilterChain(<generated>) ~[spring-security-config-4.0.4.RELEASE.jar:4.0.4.RELEASE] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_73] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_73] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_73] at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_73] at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] ... 24 common frames omitted

上面的日志显示正则表达式

/api/**

 in 

private RegexRequestMatcher unprotectedMatcher = new RegexRequestMatcher("/api/**", null);

Dangling meta character '*' near index 6 /api/**

。但我不知道这个错误意味着什么。

spring-boot spring-security csrf
4个回答
45
投票
对于那些有如何禁用特定路径的 CSRF 验证问题的人,我发现最简单的方法是创建一个带有模式的字符串数组,如下所示:

String [] publicUrls = new String [] { "/public/**", "/login", "/logout" };

这是我在 CSRF 中使用的代码。忽略 url 的代码是这样的

.ignoringAntMatchers(publicUrls)

:

.csrf() .csrfTokenRepository(csrfTokenRepository()) .ignoringAntMatchers(publicUrls)

我在

这里找到了这个。


1
投票
尝试以下操作以允许 api 调用绕过 CSRF 检查。

final String API_URL = "/api/*"; http.csrf() .requireCsrfProtectionMatcher(new RequestMatcher() { private RegexRequestMatcher requestMatcher = new RegexRequestMatcher(API_URL, null); @Override public boolean matches(HttpServletRequest request) { return !requestMatcher.matches(request); } }) .csrfTokenRepository(csrfTokenRepository());
    

0
投票
在最新版本的Spring Boot中,可以通过配置HttpSecurity对象创建SecurityFilterChain来禁用对特定URL的CSRF保护。

@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { httpSecurity.csrf((csrf) -> csrf.ignoringRequestMatchers("/trade/nextitems", "/trade/item/**")).build(); }
    

-2
投票
虽然我不知道如何使用

RegexRequestMatcher

 来匹配不受保护的 url 模式,但我找到了另一个解决方案。以下对我来说效果很好:

@Override protected void configure(HttpSecurity http) throws Exception { RequestMatcher csrfRequestMatcher = new RequestMatcher() { // Enabled CSFR protection on the following urls: private AntPathRequestMatcher[] disableCsrfMatchers = { new AntPathRequestMatcher("/api/**") }; @Override public boolean matches(HttpServletRequest request) { // If the request match one url the CSFR protection will not be enabled for (AntPathRequestMatcher rm : disableCsrfMatchers) { if (rm.matches(request)) { return false; } } return true; } // method matches }; http.csrf().requireCsrfProtectionMatcher(csrfRequestMatcher).and() .authorizeRequests().antMatchers("/**").permitAll().anyRequest().fullyAuthenticated(); }
    
© www.soinside.com 2019 - 2024. All rights reserved.