对App进行全面的安全性测试的时候,发现虽然用的https证书,但是也同时开启了允许任意http链接,导致检测的时候提示不安全
-
安卓HttpsURLConnection使用证书
//HttpsURLConnection private static void setCertificate(HttpsURLConnection connection) { InputStream caInput = null; try { CertificateFactory cf = CertificateFactory.getInstance("X.509"); caInput = MyApplication.mContext.getAssets().open("sguClass.cer"); Certificate ca = cf.generateCertificate(caInput); 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); SSLContext context = SSLContext.getInstance("TLS"); context.init(null, tmf.getTrustManagers(), null); connection.setSSLSocketFactory(context.getSocketFactory()); connection.setHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String s, SSLSession sslSession) { return true; } }); } catch (CertificateException | IOException | KeyStoreException | NoSuchAlgorithmException | KeyManagementException e) { e.printStackTrace(); } finally { try { caInput.close(); } catch (IOException e) { e.printStackTrace(); } } }
-
安卓WebView使用证书
//Webview public void onReceivedSslError(WebView webView, SslErrorHandler sslErrorHandler, SslError sslError) { // super.onReceivedSslError(webView, sslErrorHandler, sslError);//sslErrorHandler.cancel(); // sslErrorHandler.proceed(); if (chkMySSLCNCert(sslError.getCertificate())) {{//结果应该都是false,有问题的话取消验证 sslErrorHandler.proceed(); } else { sslErrorHandler.cancel(); } // if (sslError.getPrimaryError() == android.net.http.SslError.SSL_DATE_INVALID // 日期不正确 // || sslError.getPrimaryError() == android.net.http.SslError.SSL_EXPIRED // 日期不正确 // || sslError.getPrimaryError() == android.net.http.SslError.SSL_INVALID // webview BUG // || sslError.getPrimaryError() == android.net.http.SslError.SSL_UNTRUSTED) { // 根证书丢失 // if (chkMySSLCNCert(sslError.getCertificate())) { // sslErrorHandler.proceed(); // 如果证书一致,忽略错误 // } // } } private static boolean chkMySSLCNCert(SslCertificate cert) { try { //本地证书 CertificateFactory cf = CertificateFactory.getInstance("X.509"); InputStream caInput = MyApplication.mContext.getAssets().open("sguClass.cer"); Certificate ca = cf.generateCertificate(caInput); MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); byte[] caKey = sha256.digest(ca.getEncoded()); //服务端证书 Bundle bundle = SslCertificate.saveState(cert); byte[] bytes = bundle.getByteArray("x509-certificate"); Certificate certificate = cf.generateCertificate(new ByteArrayInputStream(bytes));; byte[] certificateKey = sha256.digest(certificate.getEncoded()); Log.d("test", "chkMySSLCNCert" + "caKey:" + caKey + " certificateKey: " + certificateKey); return Arrays.equals(caKey, certificateKey); } catch (CertificateException | IOException | NoSuchAlgorithmException e) { e.printStackTrace(); } return false; }
-
iOS afnetworking添加证书
//AFNetworking AFHTTPSessionManager *manager = [[AFHTTPSessionManager manager] initWithBaseURL:[NSURL URLWithString:BASE_URL_API]]; manager.securityPolicy = [self customSecurityPolicy]; + (AFSecurityPolicy *)customSecurityPolicy { NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"sguClass" ofType:@"cer"];//证书的路径 NSData *cerData = [NSData dataWithContentsOfFile:cerPath]; AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate]; securityPolicy.allowInvalidCertificates = NO;//是否允许无效证书 if (cerData) { securityPolicy.pinnedCertificates = [NSSet setWithObject:cerData]; } return securityPolicy; }
-
iOS WKWebView添加证书
//WKWebview //Allow Arbitrary Loads in Web Content设置为YES防止外部http链接打不开 - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler { NSLog(@"didReceiveAuthenticationChallenge"); //1.信任所有证书 // if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { // NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:challenge.protectionSpace.serverTrust]; // completionHandler(NSURLSessionAuthChallengeUseCredential, credential); // } //2.比较证书内容,相同的在信任 //强限制,部分部分外部资源加载不了 SecTrustRef trust = challenge.protectionSpace.serverTrust; // 从信任链返回一个证书 SecCertificateRef serverCer= SecTrustGetCertificateAtIndex(trust, 0); // SecCertificateCopyData 返回X.509证书的DER表示 NSData *serverCerData = CFBridgingRelease(SecCertificateCopyData(serverCer)); NSString *localCerPath = [[NSBundle mainBundle] pathForResource:@"sguClass" ofType:@"cer"]; NSData *localCerData = [NSData dataWithContentsOfFile:localCerPath]; if ([serverCerData isEqualToData:localCerData]) { NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:trust]; [challenge.sender useCredential:credential forAuthenticationChallenge:challenge]; completionHandler(NSURLSessionAuthChallengeUseCredential, credential); NSLog(@"服务端证书认证成功"); } else { completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, NULL); NSLog(@"服务端证书认证失败"); } }
添加完证书之后,发现会有一些问题,主要是外部http资源和第三方http链接无法访问,所以有去掉了部分验证。如果项目没有用到这些内容,还是可以添加的,更安全一些。