问题
com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
I got this error in logcat on api from 19 to 24 and there is no data loading from the server in my app I searched about that error and find that solution
@SuppressLint("TrulyRandom")
public static void handleSSLHandshake() {
try {
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
} catch (Exception ignored) {
}
}
and call it in my application class onCreate and that's solved my problem but in that answer which if find that solution there is a hint This code is not relevant and shouldn't be used! it is forbidden by Google.
so anyone knows what's the alternative solution allowed by google for that error?
回答1:
first you will need to generate your certificate file and here is the steps
go to your website link on Firefox browser
click on the green lock on the right of website link
click on more info then view certificate
a new window will appear with two taps general and details choose details
click on export to export your certificate and save this file in android project assets.
second in you project application class define hurlStack variable and use the next method in application OnCreate Method
private void handleCertificationOnOlderDevices() {
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new
BufferedInputStream(getAssets().open("porter_cert.crt"));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
Log.d("certificate", ((X509Certificate) ca).getSubjectDN().toString());
} finally {
caInput.close();
}
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
TrustManager[] trustManagers = tmf.getTrustManagers();
final X509TrustManager origTrustmanager =
(X509TrustManager) trustManagers[0];
TrustManager[] wrappedTrustManagers = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return origTrustmanager.getAcceptedIssuers();
}
public void checkClientTrusted(X509Certificate[] certs,
String authType)
{
try {
origTrustmanager.checkClientTrusted(certs, authType);
} catch (CertificateException e) {
e.printStackTrace();
}
}
public void checkServerTrusted(X509Certificate[] certs,
String authType)
{
try {
origTrustmanager.checkServerTrusted(certs, authType);
} catch (CertificateException e) {
e.printStackTrace();
}
}
}
};
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
SSLSocketFactory sslSocketFactory = context.getSocketFactory();
hurlStack = new HurlStack(null, sslSocketFactory);
} catch (Exception e) {
e.printStackTrace();
}
}
and on volley requestQueue use hurlStack
public RequestQueue getRequestQueue() {
if (requestQueue == null)
requestQueue = Volley.newRequestQueue(getApplicationContext(),
hurlStack);
return requestQueue;
}
third if you use Glide for images you will got a second error with ssl certificate related to glide and you will need to solve it by this way
1 - update in app build your gilde and okhttp3 to these version
implementation "com.squareup.okhttp3:okhttp:3.8.1"
implementation 'com.github.bumptech.glide:glide:4.9.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
implementation ('com.github.bumptech.glide:okhttp3-integration:4.9.0'){
exclude group: 'glide-parent'
}
2 - add the next class to your project
@GlideModule
public class CustomGlideModule extends AppGlideModule {
@Override
public void registerComponents(Context context, Glide glide,
Registryregistry) {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) {
OkHttpClient client =
SafeOkHttpClient.getSafeOkHttpClient(context);
OkHttpUrlLoader.Factory factory = new
OkHttpUrlLoader.Factory(client);
glide.getRegistry().replace(GlideUrl.class, InputStream.class,
factory);
}
}
}
and now glide will work fine with you.
回答2:
What is the TLS version on your server? Most likely it is 1.2 or higher. For kitkat devices, 1.2 is off by default and needs to be enabled. If your devices have Google play services you can do this via that. Otherwise you need a custom socket factory class which specifies 1.2 and probably 1.3.
If it is lower than 1.2, post Kitkat devices will not permit connections unless you trust all certs with the hack in your question. It should not be lower.
来源:https://stackoverflow.com/questions/55992416/java-security-cert-certpathvalidatorexception-trust-anchor-for-certification-pa