4

我正在尝试使 Spring 安全配置正常工作,但遇到了一些问题,我不知道该怎么做。我已经成功使用了x509,配置如下

<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>

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

感谢大家!

4

1 回答 1

3

您可以在身份验证提供程序中使用自定义 AuthenticationProvider。在实现 authenticate 方法时,您可以从 Authentication 对象中提取任何附加信息,该对象应该是 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));
    }
}
于 2013-08-16T09:42:01.477 回答