【发布时间】:2015-02-09 18:27:18
【问题描述】:
我知道这个问题已经被问过很多次,并且我已经阅读了很多解决方案,但是我无法让它们中的任何一个起作用。 所以我的主要问题是我需要使用自签名证书连接到我的服务器 - 我正在使用 tomcat 并且我已经将它配置为与 JKS 一起使用(我使用 openssl 生成了一个 .pem 文件并将它们转换为 JKS 作为在这里解释:Tomcat HTTPS keystore certificate) 从我的浏览器一切正常,但现在我需要我的应用程序通过 ssl 连接。 当我无法进行任何工作时,我尝试允许所有这样的证书:
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import javax.net.ssl.*;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
public class MyActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Thread() {
public void run() {
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
HttpGet httpGet = new HttpGet("https://MY_IP:8443");
HttpClient client = new DefaultHttpClient(ccm, params);
HttpResponse res = client.execute(httpGet);
Log.i("client", res.getStatusLine().toString());
} catch (Exception e) {
Log.e("client", "problem with connection");
}
}
}.start();
}
public class MySSLSocketFactory extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(truststore);
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;
}
};
sslContext.init(null, new TrustManager[]{tm}, null);
}
}
}
我得到这个错误:
Catch exception while startHandshake: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not
return an invalid session with invalid cipher suite of SSL_NULL_WITH_NULL_NULL
使用 http 连接它可以工作:
HttpGet httpGet = new HttpGet("http://MY_IP:8080");
我的问题是:
- 如何通过接受所有证书使其工作?
- 如何定义它只接受我的证书? (并且它将与我的 tomcat 服务器中的 JKS 匹配)
【问题讨论】:
-
我认为这是个坏主意:
ALLOW_ALL_HOSTNAME_VERIFIER.