2016-08-08 3 views
1

私はSpringブートとSpringセキュリティを使用してWebプロジェクトを作成します。 Androidデバイス用のAPIを提供するために、特定のURLパターンのCSRF保護を無効にしたいと考えています。 Spring Boot: enable the CSRF check selectively only for some requestsの第一の方法Springブートの特定のURLパターンに対するCSRF保護を無効にする

私は、次の設定を書いた:

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 

ログは、上記

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

における正規表現/api/**Dangling meta character '*' near index 6 /api/**を有することを示します。しかし、私はこのエラーが何を意味するのか分からない。

+1

'/ api/**'はant-styleパターンであり、 'RegexRequestMatcher'の代わりに' AntPathRequestMatcher'を使うべきです。または、あなたのパターンを有効な正規表現に変更してください。 – tan9

+0

はい、どうもありがとう、私は 'AntPathRequestMatcher'を使ってこの問題を解決しました。私は次の答えに自分のコードを掲載しています。 –

+0

迷惑なメタキャラクタに興味がある場合は、[正規表現の迷惑なメタキャラクタは何ですか?](https://stackoverflow.com/q/20585639/2157640)を参照してください。アスタリスクは「前の文字が0回以上繰り返されるかもしれない」という意味のメタ文字です。行の中の2つを入力するのは構文エラーですが、正規表現は実行時にのみ解析されるため、例外として現れます。 – Palec

答えて

0

CSRFチェックを回避するために、api呼び出しを許可するには、次の方法を試してください。

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

私はこの解決策をテストしました、 '/ api/*'はどんなURLパターンもできないので、これは私の質問を解決することができません –

0

私は保護されていないURLパターンを使用RegexRequestMatcherを一致させる方法を知りませんが、私は別の解決策を見つけます。以下は私のために正常に動作します:特定のパスのためにCSRFの検証を無効にする方法のこの質問を持っている人のために

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

、私は最も簡単な方法は、このように、パターンと文字列の配列を作成することであることがわかります。

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

ここはCSRFで使用しているコードです。そして、URLを無視するためのコードは、この.ignoringAntMatchers(publicUrls)です:

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

が、私はこの hereを見つけます。

関連する問題