2013-05-22 22 views
4

我想获得一个Spring安全配置工作,但我有一些问题,我不知道该怎么做。我已经成功地使用X509具有以下配置Spring-Security x509 X509PrincipalExtractor

<security:http auto-config="true" use-expressions="true"> 
    <security:x509 subject-principal-regex="CN=(.*?)," user-service-ref="rrportalUserDetailsService" /> 
    <security:intercept-url pattern="/selfRegistration/**" access="hasRole('ROLE_USER')" requires-channel="https"/> 
    <security:intercept-url pattern="/**" access="permitAll" requires-channel="http"/> 
    <security:port-mappings> 
     <security:port-mapping http="8080" https="8443"/> 
    </security:port-mappings> 
</security:http> 

的问题是,该证书的CN不够好,我适当地授权和分配我的角色。我需要解析X509Certificate扩展中的一些项目。我认为X509PrincipalExtractor对于我所需要的是完美的,但我无法弄清楚如何正确连接它。

我有这个,但我不知道我需要什么,只要AuthenticationEntrypoint。我能否实现我自己的提取并将自定义字符串传递给我的UserDetailsS​​ervice?

<security:http auto-config="false" entry-point-ref="????" use-expressions="true"> 
    <security:intercept-url pattern="/selfRegistration/**" access="hasRole('ROLE_USER')" requires-channel="https"/> 
    <security:intercept-url pattern="/**" access="permitAll" requires-channel="http"/> 
    <security:port-mappings> 
     <security:port-mapping http="8080" https="8443"/> 
    </security:port-mappings> 
    <security:custom-filter position="X509_FILTER" ref="myX509AuthenticationFilter" /> 
</security:http> 

<security:authentication-manager alias="authenticationManager"> 
    <security:authentication-provider user-service-ref="rrportalUserDetailsService"> 
    </security:authentication-provider> 
</security:authentication-manager> 

<bean id="myX509AuthenticationFilter" class="org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter"> 
    <property name="authenticationManager" ref="authenticationManager" /> 
    <property name="principalExtractor"> 
    <bean class="com.ctc.rrportal.security.rrportalX509PrincipalExtractor" /> 
    </property></bean> 

如果有人能指出我在正确的方向或指向我的示例配置,我将非常感激。

谢谢大家!

回答

3

您可以在身份验证提供程序中使用自定义AuthenticationProvider。在实现身份验证方法时,您可以从身份验证对象中提取任何其他信息,该信息应该是PreAuthenticatedAuthenticationToken的实例,并根据需要进行处理。因此,你不需要自定义的主体提取器。 DaoAuthenticationProvider默认仅支持UsernamePasswordAuthenticationToken。另一种方法是对它进行子类化并实现对两种认证令牌的支持。

public class X509AuthenticationProvider implements AuthenticationProvider { 

    private static final String CN_PATTERN = "CN=(.*?)(?:,|$)"; 
    private static final String OU_PATTERN = "OU=(.*?)(?:,|$)"; 

    private Pattern cnPattern = Pattern.compile(CN_PATTERN, Pattern.CASE_INSENSITIVE); 
    private Pattern ouPattern = Pattern.compile(OU_PATTERN, Pattern.CASE_INSENSITIVE); 

    private final UserDetailsService userDetailsService; 

    public X509AuthenticationProvider(UserDetailsService userDetailsService) { 
     Assert.notNull(userDetailsService, "UserDetailsService should be provided"); 
     this.userDetailsService = userDetailsService; 
    } 

    @Override 
    public Authentication authenticate(Authentication authentication) throws AuthenticationException { 
     final String credentials = authentication.getCredentials().toString(); 

     Matcher matcher = cnPattern.matcher(credentials); 

     if (!matcher.find()) { 
      throw new BadCredentialsException(String.format("CN not found in subject DN: {0}", credentials)); 
     } 
     String username = matcher.group(1); 

     matcher = ouPattern.matcher(credentials); 
     if (!matcher.find()) { 
      throw new BadCredentialsException(String.format("OU not found in subject DN: {0}", credentials)); 
     } 
     username = matcher.group(1) + "\\" + username; 

     final UserDetails userDetails = userDetailsService.loadUserByUsername(username); 

     return new PreAuthenticatedAuthenticationToken(userDetails, authentication.getCredentials(), userDetails.getAuthorities()); 
    } 

    @Override 
    public boolean supports(Class<?> authentication) { 
     return (PreAuthenticatedAuthenticationToken.class.isAssignableFrom(authentication)); 
    } 
} 
+0

那么X509PrincipalExtractor不是在此实例中创建的适当对象吗?看起来建立提取器是这样做的“更正确的方法”?这不正确吗? – Mike