1

我可以在Spring Security 3.2.4中鏈接多個AuthenticationEntryPoint實例嗎?Spring Security中的鏈式認證

我試圖創建以下情形:

  • 特定URL中固定使用Spring Security
  • 使用的AuthenticationEntryPointLoginUrlAuthenticationEntryPoint
  • 管理界面可以將此網址
  • 下產卵服務admin可以選擇使用CLIENT-CERT

當用戶試圖訪問安全的URL:如果路徑已經固定與CLIENT-CERT

  1. ,除非他們在UserService提供有效的證書對應於一個用戶,然後驗證失敗。標準春季安全x509認證。
  2. 一旦用戶根據第一個點進行了身份驗證,或者如果URL未使用CLIENT-CERT進行保護,則會將其定向到基於FORM的身份驗證頁面。
  3. 一旦他們成功通過用戶名和密碼進行身份驗證,它們將被引導至登錄頁面。

我在Tomcat 7.0.54上運行,用clientAuth="want"。這工作完全在一個「簡單」的春季安全設置 - 即一個WebSecurityConfigurerAdapter設置爲x509()和另一組formLogin()按照this example

所以,我希望有一個流程類似如下:

Authentication flow

我已經取得了一些成功使用DelegatingAuthenticationEntryPoint但動態地改變使用的身份驗證方法:

  • 當使用AntPathRequestMatcher/form/**映射到LoginUrlAuthenticationEntryPoint認證servlet(/j_spring_security_check)給出HTTP404錯誤。
  • 當使用AntPathRequestMatcher/cert/**映射到Http403ForbiddenEntryPoint時,用戶的詳細信息不會從提供的客戶端證書中提取,因此這會產生HTTP403錯誤。

我也看不到如何強制用戶認證兩次

我使用java-config而不是XML。

我的代碼:

我有一個DelegatingAuthenticationEntryPoint

@Bean 
public AuthenticationEntryPoint delegatingEntryPoint() { 
    final LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> map = Maps.newLinkedHashMap(); 
    map.put(new AntPathRequestMatcher("/basic/**"), new BasicAuthenticationEntryPoint()); 
    map.put(new AntPathRequestMatcher("/cert/**"), new Http403ForbiddenEntryPoint()); 

    final DelegatingAuthenticationEntryPoint entryPoint = new DelegatingAuthenticationEntryPoint(map); 
    entryPoint.setDefaultEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")); 

    return entryPoint; 
} 

而且我configure

@Override 
protected void configure(final HttpSecurity http) throws Exception { 
    defaultConfig(http) 
      .headers() 
      .contentTypeOptions() 
      .xssProtection() 
      .cacheControl() 
      .httpStrictTransportSecurity() 
      .addHeaderWriter(new XFrameOptionsHeaderWriter(SAMEORIGIN)) 
      .and() 
      .authorizeRequests() 
      .accessDecisionManager(decisionManager()) 
      .anyRequest() 
      .authenticated() 
      .and() 
      .httpBasic() 
      .authenticationEntryPoint(delegatingEntryPoint()) 
      .and() 
      .sessionManagement() 
      .maximumSessions(1) 
      .sessionRegistry(sessionRegistry()) 
      .maxSessionsPreventsLogin(true); 
} 

decisionManager()返回UnanimousBased實例。 sessionRegistry()返回一個SessionRegistryImpl實例。兩種方法都是@Bean

我添加使用自定義UserDetailsService

@Autowired 
public void configureAuthManager(
     final AuthenticationManagerBuilder authBuilder, 
     final InMemoryUserDetailsService authService) throws Exception { 
    authBuilder.userDetailsService(authService); 
} 

而且我有一個自定義FilterInvocationSecurityMetadataSource使用BeanPostProcessorthis example映射。

回答

1

鏈接多個入口點不會真正起作用。

這裏的最佳選擇可能是自定義表單登錄過程,以檢查證書是否需要(在驗證用戶之前)。這可能會簡化整體配置。它確實與普通的表單登錄設置相同。

由X509過濾器is quite minimal完成的工作。例如,您可以覆蓋attemptAuthentication方法,請致電super.attemptAuthentication(),然後檢查證書信息是否與返回的用戶身份驗證信息匹配。