我在Google Play上有一个应用程序,我收到了一封来自Google的邮件,邮件内容如下:
您的应用程序(此邮件末尾列出)使用了接口X509TrustManager的不安全实现。具体来说,当与远程主机建立HTTPS连接时,该实现会忽略所有SSL证书验证错误,从而使您的应用程序容易受到中间人攻击。
为了正确处理SSL证书验证,请更改您自定义的X509TrustManager接口的checkServerTrusted方法中的代码,以便在服务器提供的证书未满足您的要求时引发CertificateException或IllegalArgumentException异常。
我的应用程序使用“https”,我的checkServerTrusted()代码如下:
然后我修改了这个函数:
您的应用程序(此邮件末尾列出)使用了接口X509TrustManager的不安全实现。具体来说,当与远程主机建立HTTPS连接时,该实现会忽略所有SSL证书验证错误,从而使您的应用程序容易受到中间人攻击。
为了正确处理SSL证书验证,请更改您自定义的X509TrustManager接口的checkServerTrusted方法中的代码,以便在服务器提供的证书未满足您的要求时引发CertificateException或IllegalArgumentException异常。
我的应用程序使用“https”,我的checkServerTrusted()代码如下:
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;
}
};
然后我修改了这个函数:
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
if (chain == null) {
throw new IllegalArgumentException("checkServerTrusted: X509Certificate array is null");
}
if (!(chain.length > 0)) {
throw new IllegalArgumentException("checkServerTrusted: X509Certificate is empty");
}
if (!(null != authType && authType.equalsIgnoreCase("RSA"))) {
throw new CertificateException("checkServerTrusted: AuthType is not RSA");
}
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
自定义SSLSocketFactory:
public class MySSLSocketFactory extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public MySSLSocketFactory(KeyStore ctx) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(ctx);
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);
}
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
HttpClient函数:
private static HttpClient getHttpClient(int timeout) {
if (null == mHttpClient) {
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.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
ConnManagerParams.setTimeout(params, timeout);
HttpConnectionParams.setConnectionTimeout(params, timeout);
HttpConnectionParams.setSoTimeout(params, timeout);
SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));
schReg.register(new Scheme("https", sf, 443));
ClientConnectionManager conManager = new ThreadSafeClientConnManager(
params, schReg);
mHttpClient = new DefaultHttpClient(conManager, params);
} catch (Exception e) {
e.printStackTrace();
return new DefaultHttpClient();
}
}
return mHttpClient;
}
但是我对此并不了解,我只是按照电子邮件中的内容修改了我的代码,我认为我还没有解决这个问题。这个警告是什么意思?如何解决它?
TrustManager
,也许我们可以帮助指出如何实现它。例如,如果你想处理自签名证书,有相应的方法可以做到这一点。 - CommonsWarehttps
URL的Java示例都没有使用自定义的TrustManager
。这里有一个,它使用HttpURLConnection
下载PDF文件;这里有一个,它使用Retrofit从Stack Exchange API检索问题;这里是Volley的等效版本;这里是OkHttp3的等效版本。 - CommonsWare