我正在尝试按照教程制作Android自签名证书固定示例 https://www.approov.io/blog/hands-on-mobile-api-security-pinning-client-connections.html
这是我实施证书固定的课程
public class App extends Application {
final static String TAG = "App";
OkHttpClient mClient = null;
Picasso mDownloader = null;
@Override
public void onCreate() {
super.onCreate();
//---------------------------- Certificate Pinning -----------------------------//
try {
SSLContextPinner pinner = new SSLContextPinner("cert.pem");
mClient = new OkHttpClient.Builder()
.sslSocketFactory(pinner.getSSLContext().getSocketFactory(), pinner.getX509TrustManager())
.hostnameVerifier(new NoHostnameVerifier())
//.addInterceptor(new ApproovInterceptor())
.build();
} catch (Exception e) {
Log.e(TAG, e.toString());
Log.e(TAG, "Failed to pin connection");
throw new IllegalStateException("Failed to pin connection:");
}
mDownloader = new Picasso.Builder(this)
.downloader(new OkHttp3Downloader(mClient))
.build();
}
/**
* Returns a client for http requests.
*
* @returns an http client.
*/
public OkHttpClient getHttpClient() {
return mClient;
}
/**
* Returns an image downloader for http requests.
*
* @returns an http downloader.
*/
public Picasso getImageDownloader() {
return mDownloader;
}
/**
* Creates an SSL context useful for pinning certificates.
*/
private class SSLContextPinner {
private SSLContext sslContext;
private TrustManager trustManager;
public SSLContextPinner(String pemAssetName) {
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
InputStream certInputStream = getAssets().open(pemAssetName);
BufferedInputStream bis = new BufferedInputStream(certInputStream);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
int idx = -1;
while (bis.available() > 0) {
Certificate cert = certificateFactory.generateCertificate(bis);
keyStore.setCertificateEntry("" + ++idx, cert);
Log.i(TAG, "pinned " + idx + ": " + ((X509Certificate) cert).getSubjectDN());
Log.i(TAG, "ca=" + ((X509Certificate) cert).getSubjectDN());
}
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
trustManager = trustManagers[0];
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, null);
} catch (Exception e) {
sslContext = null;
trustManager = null;
Log.e(TAG, e.toString());
}
}
public SSLContext getSSLContext() {
return sslContext;
}
public X509TrustManager getX509TrustManager() {
return (X509TrustManager) trustManager;
}
}
;
/**
* Passes any host name verification.
* <p>
* There appear to be some issues when verifying absolute IP
* addresses when using subjectAltNames in certs, so we
* just pass everything for demonstration purposes.
*/
private class NoHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(final String hostname, final SSLSession session) {
Log.i(TAG, "hostnameverifier: " + hostname);
return true;
}
}
}
// end of file
cert.pem 是我的自签名证书(它也在我的服务器上使用)
如果我更改证书文件,我的示例不起作用。 它似乎运作正常。
但是,当我使用Package Capture应用程序(https://play.google.com/store/apps/details?id=app.greyshirts.sslcapture&hl=vi)测试我的示例时,它仍然有效。
如果我正确实施证书固定,我的应用程序在运行Package Capture时不起作用。
我希望有人可以帮我解释一下。谢谢!