当前位置: 首页 > 知识库问答 >
问题:

Spring Boot/Security——我可以使用X509证书作为身份验证的额外层吗?

龚浩宕
2023-03-14

我正在构建一个与我的REST API通信的Android应用程序,该API受到Spring Security的保护。

由于Android应用程序是“公共”的,没有密钥等是安全的,我想创造不同的障碍,使事情复杂化,以尽可能保护我的API。

我想增加更多安全性的一种方法是确保调用我的API的人拥有证书。我不想在我的API信任库中创建数千个证书,所以我只想确保调用者有一个证书,我把它藏在Android应用程序的密钥库中。

在我发现的例子中,Spring Security中的“正常”X509证书身份验证似乎需要每个用户都有一个唯一的证书,然后这个证书会取代基本身份验证或JWT身份验证。我希望有单独的客户端JWT令牌,但确保每次调用都带有我的一个Android应用证书,以确保(更多)有人从我的Android应用程序调用我的应用编程接口。

这是可能的,还是根本不可能?

创建RestTemplate时,可以使用密钥库和信任存储对其进行配置,这样做应该很容易。但至于保护我的REST API,它似乎更难,因为我需要证书JWT令牌或基本身份验证。

我的securityconfig没有使用XML配置。相反,我扩展了WebSecurity配置适配器。如果可以在configure(HttpSecurity-http)方法中配置,那就太好了,但我想也许我可以在OncePerRequestFilter中以某种方式实现这一点?也许在我的JwtAuthFilter之前配置一个过滤器?

编辑:在我找到的所有spring security配置示例中,他们似乎总是使用证书作为身份验证。我只想进行配置,以便在有人调用示例时。com/api/**它会进行检查,以便我的自定义信任存储批准证书(以便我“知道”这可能是来自我的应用程序的调用),但如果有人调用示例。com/website它应该使用默认的java信任存储。

如果有人举个例子。com/api/**我希望我的服务器

  1. 检查证书,如果证书未在我的自定义信任库中获得批准,请终止连接

共有1个答案

蒋鸿文
2023-03-14

我想我知道了。下面是我如何配置它的,它似乎可以工作。

“/**”endpoint是一个网站,它应该与任何没有任何特定证书的浏览器一起工作,但它需要管理员权限(您需要以管理员身份登录)。

“/api/**”“/connect/**”endpoint需要正确的证书、正确的api密钥和有效的基本或JWT令牌身份验证。

@Override
protected void configure(HttpSecurity http) throws Exception {
    
    http.authorizeRequests()
            .antMatchers("/**").hasRole("ADMIN")
        .and()
            .formLogin()
                .loginPage("/loginForm")
                .loginProcessingUrl("/authenticateTheUser")
                .permitAll()
        .and()
            .logout()
                .permitAll().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
    
    http.requestMatchers()
            .antMatchers("/connect/**","/api/**")
        .and()
            .addFilterBefore(new APIKeyFilter(null), UsernamePasswordAuthenticationFilter.class)
            .addFilterBefore(new JwtAuthorizationFilter(), BasicAuthenticationFilter.class)
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
            .httpBasic()
            .authenticationEntryPoint(authenticationEntryPoint)
        .and()
            .authorizeRequests()
            .antMatchers("/connect/**").hasAnyRole("MASTER,APPCALLER,NEGOTIATOR,MEMBER")
            .antMatchers("/api/**").hasAnyRole("MASTER,MEMBER,ANONYMOUS");
    
}

ApiKeyFilter类用于检查api-key,并确保调用中使用的证书在我的服务器信任存储中得到批准。api-key检查是我必须配置的全部,扩展的X509验证过滤器将自动检查请求证书。我的ApiKeyFilter看起来像这样:

    public class APIKeyFilter extends X509AuthenticationFilter {
    
    private String principalRequestHeader = "x-api-key";
    
    private String apiKey = "XXXX";
    
    public APIKeyFilter(String principalRequestHeader) {
        if (principalRequestHeader != null) {
            this.principalRequestHeader = principalRequestHeader;
        }
        setAuthenticationManager(new AuthenticationManager() {
            @Override
            public Authentication authenticate(Authentication authentication) throws AuthenticationException {
                if(authentication.getPrincipal() == null) {
                    throw new BadCredentialsException("Access Denied.");
                }
                String rApiKey = (String) authentication.getPrincipal();
                if (authentication.getPrincipal() != null && apiKey.equals(rApiKey)) {
                    return authentication;
                } else {
                    throw new BadCredentialsException("Access Denied.");
                }
            }
        });
    }
    
    @Override
    protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
        return request.getHeader(principalRequestHeader);
    }
    
    @Override
    protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
        X509Certificate[] certificates = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
        if (certificates != null && certificates.length > 0) {
            return certificates[0].getSubjectDN();
        }
        return super.getPreAuthenticatedCredentials(request);
    } 
}

Cred提供了这些资源,帮助我把事情整合起来:

Spring Boot-需要api密钥和x509,但不是所有endpoint都需要

具有多条路径的spring security http antMatcher

 类似资料:
  • 问题内容: 是否有人对如何使用HTTPClient 4.0.1通过x509证书执行客户端身份验证有任何友好的提示? 感谢您的时间。 问题答案: 这是一些代码,助您一臂之力。该是包含客户端证书的对象。如果服务器使用的是自签名证书,或者包含的cacerts文件中的JVM认可的不是CA所签名的证书,则需要使用。否则,要使用默认的cacerts文件,请传递给truststore参数。

  • 您好,我是Spring security的新手, 我的任务是通过匹配从x509客户端证书检索到的用户名,根据active directory对用户进行身份验证。到目前为止,我所做的是启用ssl相互身份验证 现在我有了安全措施,上面的部分工作正常。xml文件,我在其中配置了与x509参考和Active directory配置相关的所有内容 现在我面临的问题是,当我试图检索SecurityContex

  • 我有一个REST服务,它依赖于外部系统来验证令牌,但需要自己进行授权(使用like@Secured进行API级访问)。 要求: UI使用外部系统生成令牌 一种可能的解决方案是使用过滤器: > UI使用外部系统生成令牌 UI使用令牌对我的服务进行REST调用 我的服务有一个过滤器,它使用令牌调用外部系统 有效令牌的外部系统发回用户详细信息 我对成功呼叫集的服务与SecurityContextHold

  • 我正在使用SpringBoot开发具有微服务架构的Rest Backend。为了保护endpoint,我使用了JWT令牌机制。我正在使用Zuul API网关。 如果请求需要权限(来自JWT的角色),它将被转发到正确的微服务。Zuul api网关的“WebSecurityConfigrerAdapter”如下。 这样,我必须在这个类中编写每个请求授权部分。因此,我希望使用方法级安全性,即“Enabl

  • 我想在讲Grails的REST中设置基于证书的登录身份验证。 按照Burt Beckwith的文档,我使用Spring Security插件(spring-security-core:2.0-RC3)来设置X509身份验证: 生成证书文件和Tomcat配置似乎有点棘手,但已经在另一个答案中指出。我这样做了,并使用当前标准配置Tomcat 7,首先是keystoreFile、keystorePass

  • 我有一个遗留应用程序,我正在将它从用户密码转换为使用基于证书的身份验证。我使用的是Tomcat7,我的应用程序需要根据用户试图访问的应用程序中的URL支持4种类型的安全性 例如:少数servlet将使用HTTP少数servlet将使用HTTPS而不进行任何身份验证少数servlet将使用PKI进行相互身份验证,但是用户不会被预先知道,因此任何在证书链中拥有有效证书的用户都将被授予访问权限。应用程序