从 loadUserByUsername 访问证书内容

Access certificate content from loadUserByUsername

我正在开发一个 spring mvc 应用程序,它需要进行以下身份验证

  1. 通过 tomcat 证书存储
  2. 验证客户端证书
  3. 验证客户端证书的附加属性

我尝试使用 loadUserByUsername() 实现 #2,但不知道如何访问 loadUserByUsername() 中的证书内容?

我发现 this 相关。发布的答案是阅读HttpServletRequest。我可以从 loadUserByUsername() 访问 HttpServletRequest 吗?

我试过了

SecurityContextHolder.getContext().getAuthentication().getCredentials();

但身份验证对象未在 loadUserByUsername() 中设置。

更新

经过一些挖掘,我发现 Java 配置提供了一种非常简单的方法来获取 X509Certificate,只需简单地实现 AuthenticationUserDetailsS​​ervice:

@Configuration
protected static class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**")
            .x509()
            .authenticationUserDetailsService(new X509AuthenticatedUserDetailsService());
    }

    protected static class X509AuthenticatedUserDetailsService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {

        @Override
        public UserDetails loadUserDetails(PreAuthenticatedAuthenticationToken token)
                throws UsernameNotFoundException {
            X509Certificate certificate = (X509Certificate)token.getCredentials();
            // do your extra checking here...

            // add granted authorities, etc.
            Collection<GrantedAuthority> authorities = Collections.EMPTY_LIST;

            // generate your user how you deem fit
            User user = new User(certificate.getSubjectX500Principal().getName(), null, authorities);
            return user;
        }

    }
}

请注意,在 loadUserDetails 方法中,您所做的实际上与实现 UserDetailsService 时所做的相同,只是此方法采用整个 Authentication 对象。

原版

我不确定这是否是预期的方式;然而,X509Certificate 是通过在 X509AuthenticationFilter 中生成的身份验证令牌传递的。调用 PreAuthenticatedAuthenticationToken#getCredentials 应该会为您获取证书。

深入研究 API 表明 PreAuthenticatedAuthenticationProvider 可以配置自定义 UserDetailsCheckerAuthenticatedUserDetailsService。这些可能足以让您从 X509Certificate 中提取详细信息并进行验证。

在我的例子中,我确实在 UserDetailsS​​ervice 的以下实现中从 id 获取了证书 ID。 security.xml中的简单配置 public UserDetails loadUserByUsername(String id) throws UsernameNotFoundException { Security.xml

但以防万一 public class 中未调用证书 onAuthenticationSuccess myAuthSuccessHandler implements AuthenticationSuccessHandler {

有什么建议吗?想法?