如何在Spring中仅为一个用户角色启用X.509相互身份验证?

时间:2017-06-02 06:39:46

标签: java spring authentication spring-security x509

我已经构建了一个带弹簧安全性和角度前端的spring boot webapp,它使用Spring应用程序提供的REST服务。我现在有两个用户角色:

  • 用户
  • 管理

用户和管理员应通过用户名和密码进行身份验证,这已经有效,但我根本没有使用Spring用户角色。相反,我通过角度承诺休息服务和令牌(JWT)建立我自己的身份验证 现在我想添加一个Superadmin来访问与admin相同的服务,但必须使用客户端证书(X.509)进行身份验证。
如果用户是superadmin,我怎么能告诉Spring只使用X.509进行身份验证? 我是否必须使用Spring用户角色?

1 个答案:

答案 0 :(得分:0)

解决此问题的一种方法是使用自定义过滤器。在这种情况下,您可以扩展X509AuthenticationFilter。您可以覆盖过滤器的doFilter()方法并修改逻辑以检查用户类型,然后从X509AuthenticationFilter调用doFilter()方法,或者通过{{3使用您自己的AuthenticationProvider处理您的JWT }}

以下代码示例显示了如何创建和集成自定义X509AuthenticationFilter,但不打算如何启用基于X509的身份验证。

示例WebSecurityConfigurerAdapter:

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{

    @Autowired
    private CustomX509AuthenticationFilter customX509AuthenticationFilter;

    @Autowired
    private  AuthenticationProvider jwtAuthenticationProvider;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(jwtAuthenticationProvider);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.x509().x509AuthenticationFilter(customX509AuthenticationFilter);
    }
}

示例Custom X509AuthenticationFilter:

@Component
public class CustomX509AuthenticationFilter extends X509AuthenticationFilter {

    private final AuthenticationManager authenticationManager;

    @Autowired
    public CustomX509AuthenticationFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if(isAdminUser(request)){
            super.doFilter(request, response, chain);
        }
        else {
            Authentication unauthenticatedToken = getUserCredentialsFromRequest(request);
            Authentication authenticatedToken = authenticationManager.authenticate(unauthenticatedToken);
            if(authenticatedToken.isAuthenticated()) {
                SecurityContextHolder.getContext().setAuthentication(authenticatedToken);
                chain.doFilter(request, response);
            }
            else {
                throw new BadCredentialsException("Invalid Credentials");
            }
        }
    }

    private Authentication getUserCredentialsFromRequest(ServletRequest request) {
        // logic to retrieve user credentials from request and create initial Authentication
        return ...
    }

    private boolean isAdminUser(ServletRequest request) {
        // logic to determine whether or not user is admin
        return ...
    }
}