Google建议我在Android应用程序中对接口X509TrustManager进行不安全的实现,并且需要按如下方式更改我的代码:
要正确处理SSL证书验证,请更改您的代码 自定义X509TrustManager接口的checkServerTrusted方法 无论何时提出CertificateException或IllegalArgumentException 服务器提供的证书不符合您的要求 期望。对于技术问题,您可以发布到Stack Overflow 并使用标签“android-security”和“TrustManager。”
如何修改以下代码以解决上述问题?
public EasySSLSocketFactory(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;
}
};
mContext.init(null, new TrustManager[] { tm }, null);
}
答案 0 :(得分:21)
我使用以下代码解决了这个问题:
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
try {
chain[0].checkValidity();
} catch (Exception e) {
throw new CertificateException("Certificate not valid or trusted.");
}
}
答案 1 :(得分:1)
如果您在使用外部库时遇到此问题,请检查是否有appache libraray。
对我来说apache库导致了错误:我使用的是已弃用的类 - MultipartEntity。本课程使用SSLContextBuilder 它使用TrustManagerDelegate。 TrustManagerDelegate实现了X509TrustManager,它导致了TrustManager"的不安全实现。将应用程序上传到Google Play商店时出错。
解决方案是:使用MultipartEntity。
,而不是弃用MultipartEntityBuilder类例如:
MultipartEntity httpMultipart = new MultipartEntity();
String contentType = httpMultipart.getContentType().getValue();
将被替换为:
MultipartEntityBuilder httpMultipart = new MultipartEntityBuilder();
String contentType = httpMultipart.build().getContentType().getValue();
答案 2 :(得分:0)
我遇到了这个问题。如果您的代码是这样的话:
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;
}
};
它会接受所有证书,这是一个坏主意,所以谷歌发送邮件。 我们也可以进行更改以接受自签名证书。 我解决了,here is my question and my solution
答案 3 :(得分:0)
添加适用于我的OKttps的升级版在Android 10中崩溃
implementation 'com.squareup.okhttp3:okhttp:4.8.0'
答案 4 :(得分:-1)
如果您使用HttpClient
,则@Nabeel的解决方案非常好,但如果您使用的是HttpsUrlConnection
,则此代码非常适合:
import android.util.Log;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
/**
* TrustManager that accepts all certificates and hosts.
* Useful when you want to use HTTPS but you have self-signed certificates.
* Works with HttpsUrlConnection.
* Use at your own risk and only for development.
*
* @author gotev (Aleksandar Gotev)
*/
public class AllCertificatesAndHostsTruster implements TrustManager, X509TrustManager {
@Override
public final void checkClientTrusted(final X509Certificate[] xcs, final String string)
throws CertificateException {
}
@Override
public final void checkServerTrusted(final X509Certificate[] xcs, final String string)
throws CertificateException {
}
@Override
public final X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
/**
* Gets an {@link SSLContext} which trusts all certificates.
* @return {@link SSLContext}
*/
public static SSLContext getSSLContext() {
final TrustManager[] trustAllCerts =
new TrustManager[] {new AllCertificatesAndHostsTruster()};
try {
final SSLContext context = SSLContext.getInstance("SSL");
context.init(null, trustAllCerts, new SecureRandom());
return context;
} catch (Exception exc) {
Log.e("CertHostTruster", "Unable to initialize the Trust Manager to trust all the "
+ "SSL certificates and HTTPS hosts.", exc);
return null;
}
}
/**
* Creates an hostname verifier which accepts all hosts.
* @return {@link HostnameVerifier}
*/
public static HostnameVerifier getAllHostnamesVerifier() {
return new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
}
/**
* Call this method once before all your network calls
* to accept all the self-signed certificates in HTTPS connections.
*/
public static void apply() {
final TrustManager[] trustAllCerts =
new TrustManager[] {new AllCertificatesAndHostsTruster()};
try {
final SSLContext context = SSLContext.getInstance("SSL");
context.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
} catch (Exception exc) {
Log.e("CertHostTruster", "Unable to initialize the Trust Manager to trust all the "
+ "SSL certificates and HTTPS hosts.", exc);
}
}
}
来源:https://gist.github.com/gotev/6784c1303793c6ee9e56
然后使用自签名证书,只需调用:
AllCertificatesAndHostsTruster.apply();
在任何网络呼叫之前。