2015-12-15 78 views
2

我正在使用SpringBoot設計REST API。同時,我正在構建使用該API的SPA。在Spring Boot中從基本身份驗證中刪除WWW身份驗證標頭

爲了安全起見,我選擇了基本身份驗證,這很容易設置。我正面臨着401挑戰問題。當我的SPA向我的API發出請求時,如果auth失敗,瀏覽器將顯示我想要擺脫的經典登錄彈出窗口。

我讀herethere,當401響應包含值爲'Basic'的WWW驗證標頭時,瀏覽器顯示該彈出窗口。

所以要刪除這個,根據Spring Security,我將提供我自己的AuthenticationEntryPoint。有點像Spring Boot中默認的it's done。我試過這個,但它不起作用,我在運行時得到一個堆棧。有任何想法嗎?

這裏是我的代碼

@Order(SecurityProperties.BASIC_AUTH_ORDER) 
@Configuration 
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { 

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

     AuthenticationEntryPoint entryPoint = new CustomAuthenticationEntryPoint(); 

     http 
      .sessionManagement() 
       .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() 
      .authorizeRequests() 
      .regexMatchers("/api/.*").authenticated().and() 
      .httpBasic().authenticationEntryPoint(entryPoint).and() 
      .exceptionHandling().authenticationEntryPoint(entryPoint).and() 
      .csrf().disable(); 

    } 
} 

這是堆棧與mvn spring-boot:run

java.lang.reflect.InvocationTargetException 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:467) 
    at java.lang.Thread.run(Thread.java:745) 

Caused by: 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 org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built 
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:296) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:838) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) 
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) 
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) 
    at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:347) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:295) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1112) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1101) 
    at org.htulipe.WishlistApplication.main(WishlistApplication.java:44) 
... 6 more 

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built 
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) 
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) 
... 26 more 

Caused by: org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built 
at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:44) 
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration.springSecurityFilterChain(WebSecurityConfiguration.java:105) 
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$7d149fcb.CGLIB$springSecurityFilterChain$6(<generated>) 
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$7d149fcb$$FastClassBySpringCGLIB$$208d4287.invoke(<generated>) 
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) 
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:318) 
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$7d149fcb.springSecurityFilterChain(<generated>) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:497) 
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) 
... 27 more 

回答

1

發現問題運行時,我得到的,我有一個我張貼在這個問題之前發送另一組。該堆棧抱怨我的AuthenticationEntryPoint缺少Realm名稱。對於這裏的記錄是一個工作示例:

public class CustomAuthenticationEntryPoint extends BasicAuthenticationEntryPoint{ 

    public CustomAuthenticationEntryPoint() { 
     this.setRealmName("Yolo"); 
    } 

    @Override 
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) 
     throws IOException, ServletException { 
     response.setHeader("WWW-Authenticate", "FormBased"); 
     response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); 
    } 
} 
+1

另一種解決方案是不擴展'BasicAuthenticationEntryPoint',而是實現'AuthenticationEntryPoint'。他們在'BasicAuthenticationEntryPoint'中沒有做任何特殊的事情,參見https://git.io/vS31k。 –

1

我張貼這種萬一有人有類似的問題/挑戰。

允許在AuthenticationServerConfigurerAdapter類形式的認證波紋管所示:

@Override 
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { 
    oauthServer.checkTokenAccess("isAuthenticated()") 
    .allowFormAuthenticationForClients(); 
} 

這將允許您發送的client_id和client_secret形式。另外,請確保您的表單是以content-type:application/x-www-form-urlencoded表頭提交的。

4

有一個更容易的選項。只需將Http401AuthenticationEntryPoint添加到您的httpSecurity。

http.exceptionHandling() 
    .authenticationEntryPoint(new Http401AuthenticationEntryPoint("FormBased")); 
+0

你有一個xml配置的例子嗎? – tibi