我使用java在java中实现了一个FTPS客户端(FTP over SSL/TLS)apache.commons.net-框架。
它被配置为在默认端口 21 上执行显式安全性。
ftpsClient = new FTPSClient(false);
ftpsClient.setTrustManager(getConfiguration().getCertificatesManager());
ftpsClient.connect(getConfiguration().getHostName(), getConfiguration().getPort());
只要我不在服务器上强制执行客户端身份验证,一切都会正常工作。
但我需要启用客户端身份验证,因此我在服务器上强制执行它并配置了客户端系统属性:
-Djavax.net.ssl.keyStore="D:/.../ftps-client-auth.keystore"
-Djavax.net.ssl.keyStorePassword="*****"
-Djavax.net.ssl.keyStoreType=JKS
我得到的结果与没有设置系统属性时相同:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1806)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:986)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1170)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1197)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1181)
at org.apache.commons.net.ftp.FTPSClient.sslNegotiation(FTPSClient.java:265)
at org.apache.commons.net.ftp.FTPSClient._connectAction_(FTPSClient.java:207)
at org.apache.commons.net.SocketClient.connect(SocketClient.java:172)
at org.apache.commons.net.SocketClient.connect(SocketClient.java:192)
服务器日志说:
DEBUG: Client "<my ip address>", "SSL_accept failed: error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not return a certificate"
看起来是对的 - 我启用了-Djavax.net.debug=全部,这表明服务器发送了它接受的 CN 列表,但客户端发送了一个空的证书链。
- 我做错了什么?
- 我需要以编程方式进行一些配置吗?
- 证书或私钥是否需要支持 SSL/TLS 的特殊功能?
想通了:您需要以编程方式设置KeyManager
。
设置系统属性(-Djavax.net.ssl.keyStore
, ...) 还不够,因为该框架不使用 SunsSSLSocketFactory
.
Example:
ftpsClient = new FTPSClient(false);
ftpsClient.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager());
KeyManager keyManager = org.apache.commons.net.util.KeyManagerUtils.createClientKeyManager(new File(keystorePath), keystorePass);
ftpsClient.setKeyManager(keyManager);
ftpsClient.connect(getConfiguration().getHostName(), getConfiguration().getPort());
您可能想选择不同的信任管理器,例如一种基于 Java 密钥库的。 utils 也为此提供了一种方法:TrustManagerUtils.getDefaultTrustManager(keystore)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)