Java Spring REST 服务证书认证

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26635728/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 02:59:10  来源:igfitidea点击:

Spring REST Service Certificate auth

javaspringrestspring-mvcspring-security

提问by grep

I have written Spring controller. This get's requests from clients. It's just REST style.

我已经编写了 Spring 控制器。这是来自客户的请求。这只是 REST 风格。

This is very good. But I need certificate authentication. Only the clients must have access to the rest service (spring controller), which have client certificates with key (In the other words client should have keystore with key).

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

How can I configure this security to spring? Could you give me an example or link where this is written?

如何将此安全性配置为 spring?你能给我一个例子或链接在哪里写的吗?

Thanks

谢谢

采纳答案by hooknc

What you are looking for is called Mutual Authentication.

您正在寻找的是所谓的相互认证

It is the servers responsibility to make/request the client to send its certificate. Each server does this differently and you'll have to look up how to configure your particular server.

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

For Spring Security, I would recommend looking into X.509 Authentication. This type of authentication is fairly easy to use and extend as needed.

对于 Spring Security,我建议查看X.509 Authentication。这种类型的身份验证非常易于使用并根据需要进行扩展。

EDIT

编辑

So, here are a couple of references that show examples of what you are asking:

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

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

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

PDF Warning

PDF 警告

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

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

The above pdf file is no longer reachable...

上面的pdf文件已经无法访问了...

This example is really good about explaining how to setup your certificates and creating your own personal CA (Certificate Authority). Warning, the way that they show making the client certificate is just A WAY, not the way. Your client (IE web browser or java httpclient client) should determine which way to create your client certificate. Java likes to use its java keystore of course and browsers tend to like the p12 style of certificates.

这个例子非常好地解释了如何设置你的证书和创建你自己的个人 CA(证书颁发机构)。警告,他们显示制作客户端证书的方式只是一种方式,而不是方式。您的客户端(IE Web 浏览器或 java httpclient 客户端)应确定创建客户端证书的方式。Java当然喜欢使用它的Java密钥库,而浏览器往往喜欢p12风格的证书。

Final advice/warning... I don't know your level of knowledge with certificates, but... Mutual Authentication is all about who trusts whom. It is the severs responsibility to say, I need you to authenticate yourself with a certificate and here is a list of certificate providers I trust. It is then the clients responsibility to reply with a certificate signed by one of those server trusted certificate providers. It is the applications responsibility to then say, do I trust this person based on their name inside of the certificate? If and when things start to go wrong think about who is and or isn't trusting who.

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

One great tool is using -Djavax.net.debug=ssl on your application. It will show the entire ssl handshake and what is being requested and what the specific responses are. That option is a bit verbose, but it is nice to have when needed.

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

EDIT X 2

编辑 X 2

Here is how to enable mutual authentication on Tomcat 7.

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

In your server.xml config file you should see close to the following for an SSL connector:

在您的 server.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" />

The important value to note is the clientAuth value.

需要注意的重要值是 clientAuth 值。

Setting clientAuth to 'want' tells the client to send a signed client ssl certificate from a list of certificates that the server trusts if you have one. If not, go ahead and make your request as normal.

将 clientAuth 设置为 'want' 告诉客户端从服务器信任的证书列表中发送一个签名的客户端 ssl 证书(如果你有的话)。如果没有,请继续正常提出您的请求。

Setting clientAuth to 'true' tells the client that they HAVE to send a signed client ssl certificate from a list of certificates that the server trusts. If you do not have a certificate signed by a list of certificates that the server trusts, the client is NOT allowed to make the request.

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

The list of certificates that the server trusts either comes from the default java truststore or can be set using the -Djavax.net.ssl.trustStore="C:\Java\Certs\jssecacerts1"VM option.

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

Generally, when having a specific CA Certificate that you trust that isn't in the default Java truststore, the default truststore is copied, the new CA certificate is imported into the copied truststore and then used with above VM option.

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

WARNING

警告

It is super important NOT to change the default Java truststore in place. If you do, all java applications by default on that machine will be using the new updated truststore. Not always what people want and can possible cause security risks.

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

回答by jonashackt

I created a 100% comprehensible example project with everythingneeded to setup a Spring Boot app with a REST endpoint that is secured by client certificate - and a Testcase with the RestTemplate that is configured to use the client certificate to communicate with the secured Server: https://github.com/jonashackt/spring-boot-rest-clientcertificate

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

It also contains allsteps needed to generate the .key, .crtand .jksfiles. Just adjust the steps accordingly, if you don′t want to use a self-signed certificate.

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

The RestTemplate is configured like this:

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();
    }
}

Then you can use it just like you′re used to with the @Autowiredannotation inside your Test.class.

然后你就可以像@Autowired在 Test.class 中使用注解一样使用它。