我目前正在测试环境中工作,其中服务器具有默认的自签名SSL证书。我正在使用Restlet 2.1-RC2并实例化客户端资源,如下所示:
Client client = new Client(new Context(), Protocol.HTTP);
cr = new ClientResource(String.format(itql_endpoint,riQuery));
cr.setNext(client);
并重复使用客户端进行每次通话。如何设置客户端以忽略有问题的证书。
答案 0 :(得分:9)
正确方法是使用keytool
将此自签名证书导入客户端的信任存储区,例如:
keytool -import -file server-cert.pem -alias myserver -keystore mytruststore.jks
您可以直接在JRE的信任存储区(lib/security/cacerts
)中执行此操作,这可能缺乏一定的灵活性,或者在您自己的此文件副本中执行此操作,然后将其设置为信任存储区(默认情况下) OSX上的密码为changeit
或changeme
。您可以使用通常的javax.net.ssl.trustStore*
系统属性(例如-Djavax.net.ssl.trustStore=mytruststore
系统属性(和-Djavax.net.ssl.trustStorePassword
)为您的应用程序全局配置此信任库,或者您可以使用服务器上下文为Restlet中的特定连接器配置它参数,例如:
Series<Parameter> parameters = client.getContext().getParameters();
parameters.add("truststorePath", "/path/to/your/truststore.jks");
// parameters.add("truststorePassword", "password");
// parameters.add("trustPassword", "password");
// parameters.add("truststoreType", "JKS");
错误的方法是使用TrustManager
来禁用任何验证并通过SslContextFactory
(在SSL扩展名中)传递它。这些方面的东西。
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain,
String authType)
throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkServerTrusted(X509Certificate[] chain,
String authType)
throws CertificateException {
// This will never throw an exception.
// This doesn't check anything at all: it's insecure.
}
};
final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] {tm}, null);
Context context = client.getContext();
context.getAttributes().put("sslContextFactory", new SslContextFactory() {
public void init(Series<Parameter> parameters) { }
public SSLContext createSslContext() { return sslContext; }
});
虽然第一种方法似乎比第二种方法更乏味(因为您需要先获取服务器证书并复制文件),但第二种方法只是通过不验证服务器证书的任何内容而使错误消息消失从而使其容易受到MITM主动攻击。这将适用于配置此SSLContext
的任何连接。 (这种“错误的方式没有错,因为它使用了自定义SSLContext
,因为SSLContext
的这种特殊配置,这是错误的。)
答案 1 :(得分:1)
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);