最近,我使用本教程在Apache Web服务器上制作了一个自我签名的证书:
http://theheat.dk/blog/?p=1023&cpage=1
Web服务需要打开证书。在浏览器中一切顺利。我导入了证书,网站将会打开。
我从rootCA.crt,client.crt,winter fell.crt制作了BKS文件,但没有人工作。
在Android中我得到
apache日志中的SSL3_GET_CLIENT_CERTIFICATE:peer没有返回证书No CAs 已知服务器验证?
错误消息。
看来我的问题是关于发送到服务器的证书组合!在浏览器中我使用客户端和rootCA,如何将它们组合发送到webserver?
我的代码:
try {
DefaultHttpClient httpclient = new MyHttpClient(getApplicationContext());
HttpGet get = new HttpGet("https://xxx.xxx.xxx.xxx/index.php");
try {
HttpResponse response = httpclient.execute(get);
} catch (ClientProtocolException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
return "OK";
} catch (Exception err) {
return "Err";
}
并且
public class MyHttpClient extends DefaultHttpClient {
final Context context;
public MyHttpClient(Context context) {
this.context = context;
}
@Override
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
// Register for port 443 our SSLSocketFactory with our keystore
// to the ConnectionManager
registry.register(new Scheme("https", newSslSocketFactory(), 443));
return new SingleClientConnManager(getParams(), registry);
}
private SSLSocketFactory newSslSocketFactory() {
try {
// Get an instance of the Bouncy Castle KeyStore format
KeyStore trusted = KeyStore.getInstance("BKS");
// Get the raw resource, which contains the keystore with
// your trusted certificates (root and any intermediate certs)
InputStream in = context.getResources().openRawResource(R.raw.comb);
try {
// Initialize the keystore with the provided trusted certificates
// Also provide the password of the keystore
trusted.load(in, "mysecret".toCharArray());
} finally {
in.close();
}
// Pass the keystore to the SSLSocketFactory. The factory is responsible
// for the verification of the server certificate.
SSLSocketFactory sf = new SSLSocketFactory(trusted);
// Hostname verification from certificate
// http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
//sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpsURLConnection.setDefaultHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
return sf;
} catch (Exception e) {
throw new AssertionError(e);
}
}
你的帮助真的很感激!
答案 0 :(得分:1)
使用以下给定的自定义SSLSocketFactory
类。
public class AndroidSSLSocketFactory extends SSLSocketFactory {
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
"X509");
public AndroidSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(truststore);
tmf.init(truststore);
TrustManager[] trustManagers = tmf.getTrustManagers();
final X509TrustManager origTrustmanager = (X509TrustManager)trustManagers[0];
TrustManager tm = new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return origTrustmanager.getAcceptedIssuers();
}
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] chain, String authType)
throws CertificateException {
origTrustmanager.checkClientTrusted(chain, authType);
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] chain, String authType)
throws CertificateException {
origTrustmanager.checkServerTrusted(chain, authType);
}
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{tm}, null);
}
}
此类通过X509证书管理服务器和Android之间的传输层安全性。
在newSslSocketFactory()
方法中使用它。替换
SSLSocketFactory sf = new SSLSocketFactory(trusted);
使用
SSLSocketFactory sf = new AndroidSSLSocketFactory(trusted);
希望这会对你有所帮助。
信息: -
HttpClient
已弃用于Android 6.0,您应该使用HttpURLConnection
代替。Link。
更新1: -
根据{{3}}链接,以便使用自签名证书您可以创建自己的TrustManager
。因此,在TrustManager代码中进行更改。这可能有助于未来的用户。