Java:如何添加 SSL 客户端身份验证

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22460781/
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-13 15:51:10  来源:igfitidea点击:

Java: how to add SSL client-side authentication

javasslauthentication

提问by naxo

I have this code to connect the server with a client using SSL, and now I want to add client-side authentication:

我有此代码使用 SSL 将服务器与客户端连接,现在我想添加客户端身份验证:

(I have a server keystore (JCEKS type) and a client keystore (JKS type), the server uses a truststore (cacerts) where I imported both certificates because I also want to use this truststore for client authentication)

(我有一个服务器密钥库(JCEKS 类型)和一个客户端密钥库(JKS 类型),服务器使用信任库 (cacerts),我在其中导入了两个证书,因为我也想使用这个信任库进行客户端身份验证)

Client code:

客户端代码:

System.setProperty("javax.net.ssl.trustStore", cerServer);
System.setProperty("javax.net.ssl.trustStoreType","JCEKS");
System.setProperty("javax.net.ssl.trustStorePassword", pwdCacerts);

SSLSocketFactory sslsocketfactory = (SSLSocketFactory)  SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("localhost", port);

Server Code:

服务器代码:

KeyStore ks = LoadKeyStore(new File(serverKeyStore), pwdKeyStore, "JCEKS");
KeyManagerFactory kmf; 
kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, pwdKeyStore.toCharArray());

SSLContext sc = SSLContext.getInstance("SSL");
sc.init(kmf.getKeyManagers(),null, null);   

SSLServerSocketFactory ssf = sc.getServerSocketFactory(); 
sslserversocket = (SSLServerSocket) ssf.createServerSocket(port);

thanks in advance for any help.

提前感谢您的帮助。

edit: I add this code in the server side:

编辑:我在服务器端添加此代码:

System.setProperty("javax.net.ssl.trustStore", cacerts);
System.setProperty("javax.net.ssl.trustStoreType","JKS");
System.setProperty("javax.net.ssl.trustStorePassword", pwdCacerts);

but if I delete the client certificate in cacerts, the connection doesn't give me error and for that I think it's wrong that way

但是如果我在 cacerts 中删除客户端证书,连接不会给我错误,为此我认为这是错误的

采纳答案by Bruno

If you want your system to use client-certificate authentication, you'll need

如果您希望系统使用客户端证书身份验证,则需要

  • the server to request (or require) a client certificate. This is done by setting setWantClientAuth(true)on the server socket (or setNeedClientAuth, respectively). You'll also need the server to advertise the CA it accepts, which is normally done by using a truststore on the server that contains the CA by which the client-certificate chain was issued (this seems to be what you've done by setting javax.net.ssl.trustStore*on the server).

  • the client to be configured with a keystore containing the client certificate (possible the chain if there are intermediate CAs) and its private key. This can be done by setting the javax.net.ssl.keyStore*(which may affect other connections) or by using a KeyManagerFactoryin the same way as you've done it on the server side.

  • 服务器请求(或要求)客户端证书。这是通过setWantClientAuth(true)在服务器套接字(或setNeedClientAuth分别)上设置来完成的。您还需要服务器公布它接受的 CA,这通常是通过使用服务器上的信任库来完成的,该服务器包含颁发客户端证书链的 CA(这似乎是您通过设置所做的)javax.net.ssl.trustStore*在服务器上)。

  • 使用包含客户端证书(如果有中间 CA 的可能是链)及其私钥的密钥库配置的客户端。这可以通过设置javax.net.ssl.keyStore*(这可能会影响其他连接)或使用KeyManagerFactory与您在服务器端所做的相同的方式来完成。

If you use setWantClientAuth(true), you might still not get an error, since the server will accept connections that don't have a client-certificate (the server would then check the SSLSession's peer certificates to see whether there was a cert or not). setNeedClientAuth(true)would break the connection when the client doesn't present a certificate.

如果您使用setWantClientAuth(true),您可能仍然不会收到错误消息,因为服务器将接受没有客户端证书的连接(然后服务器将检查SSLSession的对等证书以查看是否有证书)。setNeedClientAuth(true)当客户端不提供证书时会中断连接。