Spring security 弹簧安全x509 x509拖拉机

Spring security 弹簧安全x509 x509拖拉机,spring-security,x509,Spring Security,X509,我正试图让一个Spring安全配置工作,但我有一些问题,我不知道该怎么办。我已成功地将x509与以下配置一起使用 <security:http auto-config="true" use-expressions="true"> <security:x509 subject-principal-regex="CN=(.*?)," user-service-ref="rrportalUserDetailsService" /> <security:in

我正试图让一个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不足以让我正确授权和分配角色。我需要解析X509证书扩展中的一些项。我认为X509拖拉机非常适合我的需要,但我不知道如何正确连接

我有这个,但就AuthenticationEntrypoint而言,我不确定我需要什么。我是否可以实现自己的提取并将自定义字符串传递给UserDetailsService

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

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


谢谢大家

您可以在身份验证提供程序中使用自定义身份验证提供程序。在实现身份验证方法时,您可以从身份验证对象中提取任何附加信息,该对象应该是PreAuthenticateAuthenticationToken的实例,并根据需要对其进行处理。因此,您不需要自定义主体提取器。默认情况下,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));
    }
}
公共类X509AuthenticationProvider实现AuthenticationProvider{
私有静态最终字符串CN_PATTERN=“CN=(.*)(:,|$)”;
私有静态最终字符串OU_PATTERN=“OU=(.*)(:,|$)”;
私有模式cnPattern=Pattern.compile(CN\u模式,Pattern.CASE\u不区分大小写);
私有模式ouPattern=Pattern.compile(OU\u模式,Pattern.CASE\u不区分大小写);
私有最终用户详细信息服务用户详细信息服务;
公共X509AuthenticationProvider(UserDetailsService UserDetailsService){
notNull(userDetailsService,“应提供userDetailsService”);
this.userDetailsService=userDetailsService;
}
@凌驾
公共身份验证(身份验证)引发AuthenticationException{
最终字符串凭据=authentication.getCredentials().toString();
Matcher Matcher=cnPattern.Matcher(凭证);
如果(!matcher.find()){
抛出新的BadCredentialsException(String.format(“在主题DN中找不到CN:{0}”,凭据));
}
字符串username=matcher.group(1);
matcher=ouPattern.matcher(凭证);
如果(!matcher.find()){
抛出新的BadCredentialsException(String.format(“在主题DN中找不到OU:{0}”,凭据));
}
username=matcher.group(1)+“\\”+用户名;
最终UserDetails UserDetails=userDetailsService.loadUserByUsername(用户名);
返回新的预验证身份验证令牌(userDetails,authentication.getCredentials(),userDetails.getAuthorities());
}
@凌驾
公共布尔支持(类身份验证){
返回(预验证DauthenticationToken.class.isAssignableFrom(验证));
}
}

那么,X509拖拉机是否不是在该实例中创建的正确对象?似乎构建提取器是“更正确”的方法?那不是真的吗?