我有一个例外:没有同行证书
当我问谷歌时,我得到了解决方案,我信任所有证书。但这个问题的答案是,它是不安全的。
所以我打电话给班级:
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
HttpClient client = new DefaultHttpClient();
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
Log.v("URL:", Url[0]);
HttpPost post = new HttpPost(Url[0]);
post.addHeader("Username", Url[1]);
post.addHeader("Passwort", Url[2]);
HttpResponse getResponse = httpClient.execute(post); //Wirft Exception
HttpEntity responseEntity = getResponse.getEntity();
UserID = Integer.parseInt(responseEntity.getContent().toString());
这是我的班级:
class MyHttpClient extends DefaultHttpClient {
final Context context;
public MyHttpClient(Context context) {
this.context = context;
}
@Override
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
// Register for port 443 our SSLSocketFactory with our keystore
// to the ConnectionManager
registry.register(new Scheme("https", (SocketFactory) 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.mykey);
try {
// Initialize the keystore with the provided trusted certificates
// Also provide the password of the keystore
trusted.load(in, "PASSWORT".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
// [url=http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506]Chapter2.Connection management[/url]
sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
return sf;
} catch (Exception e) {
throw new AssertionError(e);
}
}
}
答案 0 :(得分:7)
我发现了SSLPeerUnverifiedException的另一个可能原因:没有对等证书
如果您的模拟器的运行日期早于创建证书的日期,则可能会遇到此异常。
我的案例中的证书已于7月10日验证,但模拟器的当前日期为5月7日。
我不知道为什么我的模拟器的日期设置为5月7日,因为它应该从网络中获取时间,但这是另一个问题。
我想应该分享一下,以防万一其他人避免浪费几天时间。
答案 1 :(得分:3)
盲目地相信所有证书听起来都是一个非常糟糕的主意。你真的应该试着找出这个问题的原因。我在运行2.3.3的旧设备上遇到了同样的错误(较新的Android版本没有任何问题,iOS设备也没有问题):
javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
在阅读了几个关于SO的不同相关问题后,我得出的结论是,这可能发生在两个(可能更多?)的原因上:
在我的情况下,证书的排序不正确。作为示例,我使用来自用户this question的深刻答案从bdc发布证书订单。您可以通过终端执行以下操作来获取证书订购:
openssl s_client -connect eu.battle.net:443
(显然用你自己的服务器取代eu.battle.net)。在eu.battle.net的情况下,订单是:
Certificate chain
0 s:/C=US/ST=California/L=Irvine/O=Blizzard Entertainment, Inc./CN=*.battle.net
i:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
1 s:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
i:/C=ZA/ST=Western Cape/L=Cape Town/O=Thawte Consulting cc/OU=Certification Services Division/CN=Thawte Premium Server CA/emailAddress=premium-server@thawte.com
2 s:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
i:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
虽然应该是:
Certificate chain
0 s:/C=US/ST=California/L=Irvine/O=Blizzard Entertainment, Inc./CN=*.battle.net
i:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
1 s:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
i:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
2 s:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
i:/C=ZA/ST=Western Cape/L=Cape Town/O=Thawte Consulting cc/OU=Certification Services Division/CN=Thawte Premium Server CA/emailAddress=premium-server@thawte.com
规则是链中证书“n”的发行者应与证书“n + 1”的主题相匹配。
一旦我发现问题,更改服务器上的证书顺序是微不足道的,并且事情立即开始在Android 2.3.3设备上运行。我认为旧的Android版本对于证书订单有点麻烦,但这也是一个噩梦,因为较新的Android版本会自动重新排序证书。地狱,即使是旧版的iPhone 3GS也无法使用证书。