春季 REST 服务证书认证

2022-09-03 05:36:33

我写了弹簧控制器。此 get 来自客户端的请求。这只是 REST 风格。

这非常好。但我需要证书身份验证。只有客户端必须有权访问 rest 服务(spring 控制器),该服务具有带有密钥的客户端证书(换句话说,客户端应具有带有密钥的密钥库)。

如何将此安全性配置为弹簧?你能给我一个例子或链接写这个吗?

谢谢


答案 1

您要查找的内容称为相互身份验证

服务器负责使/请求客户端发送其证书。每个服务器都以不同的方式执行此操作,您必须查找如何配置特定服务器。

对于Spring Security,我建议研究X.509身份验证。这种类型的身份验证相当易于使用,并根据需要进行扩展。

编辑

因此,这里有一些参考资料,显示了您所问的示例:

http://whiteycode.blogspot.com/2012/04/part-3-x509-authentication-with-spring.html

警告

http://www.promixis.com/pdfs/SpringSecurityAndX509ClientCertificates.pdf

上述pdf文件不再可访问...

此示例非常有助于说明如何设置证书和创建自己的个人 CA(证书颁发机构)。警告,他们显示制作客户端证书的方式只是一种方式,而不是方式。您的客户端(IE Web 浏览器或 java httpclient 客户端)应确定创建客户端证书的方法。Java当然喜欢使用它的java密钥库,浏览器倾向于喜欢p12风格的证书。

最终建议/警告...我不知道你对证书的了解程度,但是...相互身份验证就是关于谁信任谁。这是服务器的责任,说,我需要你用证书对自己进行身份验证,这是我信任的证书提供商列表。然后,客户端负责使用由这些服务器受信任的证书提供程序之一签名的证书进行回复。然后,应用程序有责任说,我是否根据证书中的姓名信任此人?如果事情开始出错,想想谁是,或者不信任谁。

一个很棒的工具是在应用程序上使用 -Djavax.net.debug=ssl。它将显示整个 ssl 握手、请求的内容以及具体的响应。该选项有点冗长,但在需要时可以很好地使用。

编辑 X 2

以下是如何在Tomcat 7上启用相互身份验证。

在服务器.xml配置文件中,您应该看到 SSL 连接器的以下内容:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
           clientAuth="want" sslProtocol="TLS"
           keystoreFile="C:\Java\Certs\localhost.jks"
           keystorePass="changeit"
           URIEncoding="UTF-8" />

要注意的重要值是 clientAuth 值。

将 clientAuth 设置为“想要”会告诉客户端从服务器信任的证书列表中发送已签名的客户端 SSL 证书(如果有)。如果没有,请继续并像往常一样提出您的请求。

将 clientAuth 设置为“true”会告诉客户端,他们必须从服务器信任的证书列表中发送已签名的客户端 SSL 证书。如果没有由服务器信任的证书列表签名的证书,则不允许客户端发出请求。

服务器信任的证书列表要么来自缺省 java 信任库,要么可以使用 VM 选项进行设置。-Djavax.net.ssl.trustStore="C:\Java\Certs\jssecacerts1"

通常,当具有您信任的特定 CA 证书不在缺省 Java 信任库中时,将复制缺省信任库,将新的 CA 证书导入到复制的信任库中,然后与上述 VM 选项一起使用。

警告

不要就地更改缺省的 Java 信任库,这一点非常重要。如果这样做,缺省情况下,该机器上的所有 Java 应用程序都将使用新更新的信任库。并不总是人们想要的,并且可能导致安全风险。


答案 2

我创建了一个100%可理解的示例项目,其中包含设置具有由客户端证书保护的REST端点的Spring Boot应用程序所需的一 - 以及一个具有RestTemplate的Testcase,该模板配置为使用客户端证书与受保护的服务器进行通信:https://github.com/jonashackt/spring-boot-rest-clientcertificate

它还包含生成 和 文件所需的所有步骤。如果您不想使用自签名证书,只需相应地调整步骤即可。.key.crt.jks

RestTemplate 的配置如下:

package de.jonashackt.restexamples;

import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.util.ResourceUtils;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;

@Configuration
public class RestClientCertTestConfiguration {

    private String allPassword = "allpassword";

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) throws Exception {

        SSLContext sslContext = SSLContextBuilder
                .create()
                .loadKeyMaterial(ResourceUtils.getFile("classpath:keystore.jks"), allPassword.toCharArray(), allPassword.toCharArray())
                .loadTrustMaterial(ResourceUtils.getFile("classpath:truststore.jks"), allPassword.toCharArray())
                .build();

        HttpClient client = HttpClients.custom()
                .setSSLContext(sslContext)
                .build();

        return builder
                .requestFactory(new HttpComponentsClientHttpRequestFactory(client))
                .build();
    }
}

然后,您可以像习惯的那样使用它,就像在 Test.class 中的注释一样。@Autowired