vik*_*s27 10 java ssl restlet sslhandshakeexception restlet-2.3.1
我正在本地测试客户端和服务器之间的SSL通信.所以我使用OpenSSL命令生成证书.在cacert文件中添加了此证书.还生成.p12文件.
我在服务器和客户端使用相同的.p12文件.这是服务器代码
Server server = component.getServers().add(Protocol.HTTPS, port);
Series<Parameter> params = server.getContext().getParameters();
params.add("keystorePath", ".p12 file path");
params.add("keystoreType", "PKCS12");
params.add("needClientAuthentication","true");
component.getDefaultHost().attach("", "/AA"), new AAClass());
component.start();
Run Code Online (Sandbox Code Playgroud)
这是客户端代码:
Client client = trustAllCerts();
clientResource = new ClientResource(url);
clientResource.setNext(client);
try{
clientText = clientResource.post"");
}
catch(ResourceException e){
e.printStackTrace();
}
public Client trustAllCerts() {
Client client = null;
try {
client = new Client(new Context(), Protocol.HTTPS);
Context context = client.getContext();
final SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
context.getAttributes().put("sslContextFactory", new SslContextFactory() {
public void init(Series<Parameter> parameters) {
}
public SSLContext createSslContext() {
return sslContext;
}
});
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
context.getAttributes().put("hostnameVerifier", new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
sslContext.init(null, new TrustManager[] { tm }, null);
} catch (KeyManagementException e) {
LOGGER.error("Exception in Key Management" + e);
} catch (NoSuchAlgorithmException e) {
LOGGER.error("Exception in Algorithm Used" + e);
}
return client;
}
Run Code Online (Sandbox Code Playgroud)
我得到以下异常:
Restlet-1299242, fatal error: 42: null cert chain
javax.net.ssl.SSLHandshakeException: null cert chain
%% Invalidated: [Session-25, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256]
Restlet-1299242, SEND TLSv1.2 ALERT: fatal, description = bad_certificate
Restlet-1299242, WRITE: TLSv1.2 Alert, length = 2
Restlet-1299242, fatal: engine already closed. Rethrowing javax.net.ssl.SSLHandshakeException: null cert chain
Restlet-1299242, called closeInbound()
Restlet-1299242, fatal: engine already closed. Rethrowing javax.net.ssl.SSLException: Inbound closed before receiving peer's close_notify: possible truncation attack?
Restlet-1299242, called closeOutbound()
Restlet-1299242, closeOutboundInternal()
Run Code Online (Sandbox Code Playgroud)
我尝试使用System.setProperty()添加密钥库和信任库,但它不起作用.
请帮忙.提前致谢.
首先,让我们创建一个JKS格式的密钥库.PKCS12通常用于浏览器,默认的java应用程序使用JKS(据我所知).Java也支持PKCS12,但我不知道它的确切参数.
准备JKS文件
让我们查看我们的PKCS12文件并获取我们想要提取JKS文件的证书别名.
keytool -list \
-keystore [*.p12 file] \
-storepass [password] \
-storetype PKCS12 \
-v
Run Code Online (Sandbox Code Playgroud)
请注意要导出的别名.现在让我们创建一个JKS文件.
keytool -keystore [*.jks file path] -genkey -alias client
Run Code Online (Sandbox Code Playgroud)
这会问一堆问题.你可以随意填写它们.现在,您可以将别名从*.p12文件导出到*.jks文件.
keytool -importkeystore \
-srckeystore [*.p12 file path] \
-srcstoretype pkcs12 \
-srcalias [alias from first command] \
-destkeystore [*.jks file path] \
-deststoretype jks \
-deststorepass [*.jks file password] \
-destalias [new alias]
Run Code Online (Sandbox Code Playgroud)
如果您没有任何PKCS12文件,或者您的证书是CER,DER或PEM格式,则可以使用以下命令将证书添加到密钥库.
keytool -import \
-alias [new alias] \
-keystore [*.jks file path] \
-file [*.DER file path]
Run Code Online (Sandbox Code Playgroud)
请确保您已导入,您的证书,证书提供商的证书(中间证书)和根证书.
现在,您可以检查您的JKS文件是否包含您需要的所有证书.
keytool -list \
-keystore [*.jks file path] \
-storepass [password] \
-storetype jks \
-v
Run Code Online (Sandbox Code Playgroud)
设置服务器
您可以在客户端和服务器端使用JKS文件.根据Restlet文档,您可以使用这样的JKS文件来提供HTTPS连接.
Server server = component.getServers().add(Protocol.HTTPS, port);
Series<Parameter> parameters = server.getContext().getParameters();
parameters.add("sslContextFactory","org.restlet.engine.ssl.DefaultSslContextFactory");
parameters.add("keyStorePath", "*.jks file");
parameters.add("keyStorePassword", "password");
parameters.add("keyPassword", "password");
parameters.add("keyStoreType", "JKS");
Run Code Online (Sandbox Code Playgroud)
之后,如果您从浏览器检查端口,则必须看到安全标志.或者您可以使用一些在线工具(如此)来检查您的证书.
设置客户端
现在让我们来看看客户端.由于您正在开发应用程序的两端,因此您可以使用已创建的JKS文件.
Context con = new Context();
Series<Parameter> clParameters = con.getParameters();
clParameters.add("truststorePath", "*.jks file");
clParameters.add("truststorePassword", "password");
clParameters.add("truststoreType", "JKS");
Client restletClient = new Client(con, Protocol.HTTPS);
Run Code Online (Sandbox Code Playgroud)
在测试时或在其他情况下,您的证书主机名和实际主机名可能不匹配.要禁用主机名检查,可以将此块添加到应用程序中.
static{
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
new javax.net.ssl.HostnameVerifier(){
public boolean verify(String hostname,
javax.net.ssl.SSLSession sslSession ) {
return true ;
}
});
}
Run Code Online (Sandbox Code Playgroud)
一些想法
由于我无法在我的语言环境中测试它,因此我不确定您的客户端和服务器JKS文件必须是否相同.您可能只需要将自己的证书添加到server.jks.SSL和证书对我来说总是很棘手.经过一些试验和错误,我通常会让它工作.我希望这能帮到您.
此外,您可能还需要考虑使用反向代理类型的Web服务器,如Apache2或Nginx.如果要使用它们,则必须将证书合并到单个文件中.如果查看证书文件,您会看到每个文件(您自己的证书,中间证书和根证书)都是这样的
-----BEGIN CERTIFICATE-----
MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUA...
....
-----END CERTIFICATE-----
Run Code Online (Sandbox Code Playgroud)
您只需将一个添加到另一个即可创建合并证书.而不是使用该证书来结束Apache2或Nginx上的SSL.这就是我通常做的事情.但是在客户端,您仍然需要创建JKS文件.
我在服务器和客户端使用相同的 .p12 文件
这已经是一个错误。客户端和服务器是不同的身份,不应具有相同的私钥、公钥或证书。
我建议你放弃所有 OpenSSL 的东西,然后重新开始keytool
,如下所示:
-trustcacerts
选项导入签名者的证书链;并使用创建密钥对和 CSR 时使用的相同别名导入签名证书。你完成了。把...忘了吧
trustAllCerts
、自定义的TrustManagers
和任何类型的自定义代码javax.net.ssl.keyStore
和javax.net.ssl.keyStorePassword
步骤 (1) 和 (2) 是打算如何完成的。离开那些,你就会陷入麻烦和冲突。
归档时间: |
|
查看次数: |
18267 次 |
最近记录: |