X509TrustManager 是否在每个 Android 应用程序会话中仅检查一次 API 请求?
Does X509TrustManager check API requests only one time per Android Application session?
Recently I have implemented a security feature to check my request is connected with the valid host. For that, I'm checking the certs of that host and I used X509TrustManager for that case. So if X509TrustManager found some invalid cert it will throw an exception and according to that, I will show an alert to the user. But the issue is that X509TrustManager throws an exception only first time. But when I refresh the same request I did not catch invalid certification and I did not see any alert. Below I added my implementation. Let me know any issue with my implementation or any known issue with X509TrustManager.
Thanks and Regards.
final X509TrustManager finalTrustManager = x509TrustManager;
TrustManager[] trustAllCerts = new TrustManager[0];
if (finalTrustManager != null) {
trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return finalTrustManager.getAcceptedIssuers();
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
try {
// If Application get any CertificateException in Splash screen we will show related alert in MainActivity
// We need to terminate app after showing alert but if we show alert in Splash screen it will get hide when Main Activity get visible.
// To avoid this scenario we added this implementation.
if (mIsSplashGetInvalidateCertificate && !(mLifecycleManager.getCurrentStackOfActivity().get(0) instanceof SplashActivity)) {
mAlertManager.showAlertMessageWithoutDuplicates(mLifecycleManager.getCurrentContext().getResources().getString(R.string.certificate_error_title), mLifecycleManager.getCurrentContext().getResources().getString(R.string.certificate_error_message), (FragmentActivity) mLifecycleManager.getCurrentStackOfActivity().get(0), true);
}
// Checking the certificate availability of host
if ((certs != null && certs.length != 0) && (authType != null && authType.length() != 0)) {
finalTrustManager.checkClientTrusted(certs, authType);
} else {
terminateApplicationWithAlert();
}
} catch (CertificateException e) {
terminateApplicationWithAlert();
}
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
try {
if (mIsSplashGetInvalidateCertificate && !(mLifecycleManager.getCurrentStackOfActivity().get(0) instanceof SplashActivity)) {
mAlertManager.showAlertMessageWithoutDuplicates(mLifecycleManager.getCurrentContext().getResources().getString(R.string.certificate_error_title), mLifecycleManager.getCurrentContext().getResources().getString(R.string.certificate_error_message), (FragmentActivity) mLifecycleManager.getCurrentStackOfActivity().get(0), true);
}
if ((certs != null && certs.length != 0) && (authType != null && authType.length() != 0)) {
finalTrustManager.checkServerTrusted(certs, authType);
} else {
terminateApplicationWithAlert();
}
} catch (CertificateException e) {
terminateApplicationWithAlert();
}
}
}
};
}
您实际上并没有将证书标记为无效,因为您正在捕获 CertificateException
并吞下它。通过不抛出 CertificateException
,您是在告诉 HTTP 库无效证书是有效的,它可能正在缓存它以避免多次重新验证证书。
您需要允许 CertificateException
从 X509TrustManager
方法中抛出,在 HTTP 调用站点捕获错误,并从那里显示对话框。
Recently I have implemented a security feature to check my request is connected with the valid host. For that, I'm checking the certs of that host and I used X509TrustManager for that case. So if X509TrustManager found some invalid cert it will throw an exception and according to that, I will show an alert to the user. But the issue is that X509TrustManager throws an exception only first time. But when I refresh the same request I did not catch invalid certification and I did not see any alert. Below I added my implementation. Let me know any issue with my implementation or any known issue with X509TrustManager. Thanks and Regards.
final X509TrustManager finalTrustManager = x509TrustManager;
TrustManager[] trustAllCerts = new TrustManager[0];
if (finalTrustManager != null) {
trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return finalTrustManager.getAcceptedIssuers();
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
try {
// If Application get any CertificateException in Splash screen we will show related alert in MainActivity
// We need to terminate app after showing alert but if we show alert in Splash screen it will get hide when Main Activity get visible.
// To avoid this scenario we added this implementation.
if (mIsSplashGetInvalidateCertificate && !(mLifecycleManager.getCurrentStackOfActivity().get(0) instanceof SplashActivity)) {
mAlertManager.showAlertMessageWithoutDuplicates(mLifecycleManager.getCurrentContext().getResources().getString(R.string.certificate_error_title), mLifecycleManager.getCurrentContext().getResources().getString(R.string.certificate_error_message), (FragmentActivity) mLifecycleManager.getCurrentStackOfActivity().get(0), true);
}
// Checking the certificate availability of host
if ((certs != null && certs.length != 0) && (authType != null && authType.length() != 0)) {
finalTrustManager.checkClientTrusted(certs, authType);
} else {
terminateApplicationWithAlert();
}
} catch (CertificateException e) {
terminateApplicationWithAlert();
}
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
try {
if (mIsSplashGetInvalidateCertificate && !(mLifecycleManager.getCurrentStackOfActivity().get(0) instanceof SplashActivity)) {
mAlertManager.showAlertMessageWithoutDuplicates(mLifecycleManager.getCurrentContext().getResources().getString(R.string.certificate_error_title), mLifecycleManager.getCurrentContext().getResources().getString(R.string.certificate_error_message), (FragmentActivity) mLifecycleManager.getCurrentStackOfActivity().get(0), true);
}
if ((certs != null && certs.length != 0) && (authType != null && authType.length() != 0)) {
finalTrustManager.checkServerTrusted(certs, authType);
} else {
terminateApplicationWithAlert();
}
} catch (CertificateException e) {
terminateApplicationWithAlert();
}
}
}
};
}
您实际上并没有将证书标记为无效,因为您正在捕获 CertificateException
并吞下它。通过不抛出 CertificateException
,您是在告诉 HTTP 库无效证书是有效的,它可能正在缓存它以避免多次重新验证证书。
您需要允许 CertificateException
从 X509TrustManager
方法中抛出,在 HTTP 调用站点捕获错误,并从那里显示对话框。