2015-12-15 38 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