2016-11-22 163 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