2016-11-22 182 views
1

我有一个auth-cas库,为我的spring启动项目提供身份验证。 在这个AUTH-CAS库有扩展 WebSecurityConfigurerAdapter具有以下配置功能春季启动安全 - 多个WebSecurityConfigurerAdapter

@Override 
@ConditionalOnProperty(value = "ugent.cas.serviceUrl", matchIfMissing = true) 
@ConditionalOnClass(Cas.class) 
protected void configure(HttpSecurity http) throws Exception { 
    http.exceptionHandling().authenticationEntryPoint(casAuthenticationEntryPoint()); 

    if (basicAuthenticationProviders != null) { 
     http.addFilter(basicAuthFilter()); 
    } 

    http.addFilter(casAuthenticationFilter()) 
      .addFilter(requestSSOLogoutToCASServerLogoutFilter()) 
      .logout() 
      .deleteCookies("JSESSIONID") 
      .permitAll() 
      .logoutSuccessUrl("/logout.html") 
      .and() 
      .csrf() 
      .disable() 
      .headers() 
      .frameOptions() 
      .disable(); 

    http.authorizeRequests() 
      .antMatchers(HttpMethod.OPTIONS, "/api/**").permitAll() 
      .antMatchers("/**").authenticated(); 
} 

由于这应该是黑盒子我添加了一个类我自己WebSecurityConfigurerAdapter,看起来像这样:

@Configuration 
//@Order(Integer.MAX_VALUE) 
//@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) 
@Order(1) 
public class AuthSecurityConfiguration extends WebSecurityConfigurerAdapter { 

    @Override 
    public void configure(WebSecurity webSecurity) throws Exception { 
     webSecurity 
       .ignoring() 
       // All of Spring Security will ignore the requests 
       .antMatchers("/choose.html") 
       .antMatchers("/account/*"); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http/*.addFilter(usernamePasswordAuthenticationFilter()) 
       .formLogin() 
       .permitAll() 
       .and() 
       .logout() 
       .deleteCookies("JSESSIONID") 
       .permitAll() 
       .logoutSuccessUrl("/logout.html") 
       .and() 
       .csrf() 
       .disable() 
       .headers() 
       .frameOptions() 
       .disable(); 
      */  

       .authorizeRequests() 
       .anyRequest().authenticated() 
       .and() 
       .authenticationProvider(AuthenticationProvider()) 
       .formLogin() 
       .permitAll() 
       .and() 
       .csrf() 
       .disable() 
       .headers() 
       .frameOptions() 
       .disable() 
       ; 

    } 

    @Bean 
    public AuthenticationProvider AuthenticationProvider() { 
     return new LCAAuthenticationProvider(); 
    } 

    @Bean 
    public UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter() throws Exception{ 
     UsernamePasswordAuthenticationFilter filter = new UsernamePasswordAuthenticationFilter(); 
     filter.setAuthenticationManager(authenticationManager()); 
     return filter; 
    } 
} 

我的自定义AuthenticationProvider实现'AuthenticationProvider',并在页面中工作将我重定向到/登录页面,并且我可以用我的用户群中的凭据登录。 唯一的问题是当我已经在另一个auth cas网络上登录时,我应该进行身份验证,但它仍然会用我的自定义身份验证提供程序提示我。

如何配置HttpSecurity以使其与我的2个身份验证提供程序配合使用。

其他相关的问题,我怎么能从被忽略的页面/choose.html提供登录到2个身份验证提供程序之一的选项?

编辑

这是我目前'WebSecurityConfigurererAdapter'

@Configuration 
//@Order(Integer.MAX_VALUE) 
//@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) 
@Order(0) 
public class AuthSecurityConfiguration extends WebSecurityConfigurerAdapter { 

    /** 
    * The authProvider bean used as a cas authentication provider. 
    */ 
    @Autowired 
    private LCAAuthenticationProvider authProvider; 

    @Override 
    public void configure(WebSecurity webSecurity) throws Exception { 
     webSecurity 
       .ignoring() 
       // All of Spring Security will ignore the requests 
       .antMatchers("/choose.html") 
       .antMatchers("/account/*"); 
    } 

    @Autowired 
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 
     auth.authenticationProvider(authProvider); 
    } 

     /** 
    * The authenticationManagerBean bean. 
    * 
    * @return the authenticationManagerBean 
    * @throws Exception 
    */ 
    @Override 
    public AuthenticationManager authenticationManagerBean() throws Exception { 
     return super.authenticationManagerBean(); 
    } 

    /** 
    * The loginUrlAuthenticationEntryPoint bean 
    * 
    * @return the loginUrlAuthenticationEntryPoint 
    */ 
    @Bean 
    public LoginUrlAuthenticationEntryPoint loginUrlAuthenticationEntryPoint() { 
     LoginUrlAuthenticationEntryPoint ep = new LoginUrlAuthenticationEntryPoint("/choose.html"); 
     //ep.setLoginUrl(cas.getLoginUrl()); 

     return ep; 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.exceptionHandling().authenticationEntryPoint(loginUrlAuthenticationEntryPoint()); 

     http.addFilter(usernamePasswordAuthenticationFilter()) 
       .formLogin() 
       .permitAll() 
       .and() 
       .logout() 
       .deleteCookies("JSESSIONID") 
       .permitAll() 
       .logoutSuccessUrl("/logout.html") 
       .and() 
       .csrf() 
       .disable() 
       .headers() 
       .frameOptions() 
       .disable(); 
      /* 

       .authorizeRequests() 
       .anyRequest().authenticated() 
       .and() 
       .authenticationProvider(AuthenticationProvider()) 
       .formLogin() 
       .loginPage("choose.html") 
       .permitAll() 
       .and() 
       .csrf() 
       .disable() 
       .headers() 
       .frameOptions() 
       .disable() 
       ; 
      */ 
    } 

    @Bean 
    public LCAAuthenticationProvider lcaAuthenticationProvider() { 
     return new LCAAuthenticationProvider(); 
    } 

    @Bean 
    public UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter() throws Exception{ 
     UsernamePasswordAuthenticationFilter filter = new UsernamePasswordAuthenticationFilter(); 
     filter.setAuthenticationManager(authenticationManager()); 
     return filter; 
    } 
} 

的配置但我发现了以下错误:

Exception in thread "main" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException 
     at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:62) 
     at java.lang.Thread.run(Unknown Source) 
Caused by: java.lang.reflect.InvocationTargetException 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
     at java.lang.reflect.Method.invoke(Unknown Source) 
     at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:54) 
     ... 1 more 
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:839) 
     at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) 
     at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) 
     at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766) 
     at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361) 
     at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) 
     at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191) 
     at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180) 
     at be.ugent.lca.Application.main(Application.java:16) 
     ... 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$$699e3cc3.CGLIB$springSecurityFilterChain$2(<generated>) 
     at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$699e3cc3$$FastClassBySpringCGLIB$$e656a0ba.invoke(<generated>) 
     at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) 
     at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:355) 
     at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$699e3cc3.springSecurityFilterChain(<generated>) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
     at java.lang.reflect.Method.invoke(Unknown Source) 
     at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) 

我可以跟踪误差行44在https://github.com/spring-projects/spring-security/blob/master/config/src/main/java/org/springframework/security/config/annotation/AbstractSecurityBuilder.java但我找不到是什么原因造成的

+0

downvote的任何理由?我很乐意编辑与建议相对应的问题。 – turoni

回答

1

您需要将auth过滤器和用户名密码过滤器置于您自己的配置(AuthSecurityConfiguration)中,然后将其设置为第一个,然后为choose.html定义一个入口点,并使用过滤器处理来自choose.html的请求,然后重定向到不同的URL(例如/ login或/ auth)取决于选择。所以它会像下面。(我已经做了这样的事情之前,所以我只是复制它们,你可以改变你自己的)

<security:http xmlns="http://www.springframework.org/schema/security" entry-point-ref="clientAuthenticationEntryPoint"> 
     <intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" /> 
     <intercept-url pattern="/choose.html" access="IS_AUTHENTICATED_ANONYMOUSLY" /> 
     <intercept-url pattern="/autherror" access="IS_AUTHENTICATED_ANONYMOUSLY" /> 
     <intercept-url pattern="/**/**" access="IS_AUTHENTICATED_FULLY"/> 
     <custom-filter ref="logoutFilter" position="LOGOUT_FILTER" /> 
     <custom-filter ref="authenticationBrokerProcessingFilter" after="LOGOUT_FILTER" /> 
     <custom-filter ref="oauth2ClientContextFilter" after="EXCEPTION_TRANSLATION_FILTER"/> 
     <custom-filter ref="oAuth2AuthenticationProcessingFilter" before="FILTER_SECURITY_INTERCEPTOR"/> 
     <form-login 
       login-page="/login" 
       default-target-url="/main" 
       username-parameter="username" 
       password-parameter="password" 
       login-processing-url="/loginSubmit" 
       authentication-failure-handler-ref="passwordFailureHandler" 
       authentication-success-handler-ref="passwordAuthenticationSuccessHandler" 
       always-use-default-target="false" 
       /> 
     <csrf /> 
     <access-denied-handler ref="accessDeniedHandler" /> 
    </security:http> 


<bean id="clientAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"> 
     <constructor-arg name="loginFormUrl" value="/choose.html"/> 
    </bean> 

正如你所看到的XML,有两个身份验证方法,auth2和用户名密码。 authenticationBrokerProcessingFilter将处理来自choose.html的请求;

用户名密码过滤器将处理请求/loginSubmitlogin页;

auth2过滤器将使用代码处理来自sso的请求/oauth2-login

+0

我使用弹簧启动,所以我不认为我可以做任何XML配置。 – turoni

+0

您可以将这些xml更改为Java。 – chaoluo

+0

如何?解决我的问题的基于注释的解决方案我将奖励赏金。 – turoni