当前位置: 首页 > 面试题库 >

Okhttp3-接受所有证书并使用证书

淳于典
2023-03-14
问题内容

我正在尝试固定服务器的自签名证书。我的OkHttpClient使用两个参数,第一个是ssl Socket Factory:

final TrustManager[] trustAllCerts = new TrustManager[] {
        new X509TrustManager() {
            @SuppressLint("TrustAllX509TrustManager")
            @Override
            public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {}

            @SuppressLint("TrustAllX509TrustManager")
            @Override
            public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {}

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                  return new X509Certificate[0];
            }
         }
     };

// Install the all-trusting trust manager
SSLContext sslContext;
try {
     sslContext = SSLContext.getInstance("SSL");
     sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
 } catch (NoSuchAlgorithmException | KeyManagementException e) {
     e.printStackTrace();
     FirebaseCrash.report(e);
     return null;
}

// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

其次是证书固定器:

new CertificatePinner.Builder()
    .add("bogus.com", "sha1/BOGUS")
    .build()

注意:如果我不添加certificatePinner,则一切正常。问题是执行请求时,将调用CertificatePinner.check():

if (pins.isEmpty()) return;

显然,如果我确实设置了一个(非空的)certificatePinner,则该方法不会在那里停止,而是会继续。然后,它继续检查
“为我的主机名固定的证书中至少有一个是受信任的证书”

问题是我在我的TrustManager的getAcceptedIssuers中传递了一个空数组-这意味着自签名证书将触发异常,因为在“
getAcceptedIssues”中未明确信任该异常。似乎无法固定“ getAcceptedIssuers”中未明确信任的证书。

有什么办法可以解决这个问题?是设计使然吗?

这就是我建立OkHttpClient的方式:

OkHttpClient client = new OkHttpClient.Builder()
    .sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0])
    .certificatePinner(certPinner)
    .readTimeout(10, TimeUnit.SECONDS)
    .connectTimeout(10, TimeUnit.SECONDS)
    .build();

问题答案:

TrustManager,CertificatePinner和主机名验证都做不同但重要的事情。如果您要使用自签名证书但仍然具有安全性,而不是仅仅为了便于本地开发而与自签名证书相反,那么您可能要创建一个有效的TrustManager。

例如https://github.com/yschimke/oksocial/blob/3757196cde420b9d0fe37cf385b66f4cdafb1ae1/src/main/java/com/baulsupp/oksocial/security/CertificateUtils.java#L19

  public static X509TrustManager load(List<File> serverCerts)
      throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException {
    return trustManagerForKeyStore(keyStoreForCerts(serverCerts));
  }

  public static X509TrustManager trustManagerForKeyStore(KeyStore ks)
      throws NoSuchAlhtml" target="_blank">gorithmException, KeyStoreException {
    TrustManagerFactory tmf =
        TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

    tmf.init(ks);

    return (X509TrustManager) tmf.getTrustManagers()[0];
  }

  public static KeyStore keyStoreForCerts(List<File> serverCerts)
      throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException {
    CertificateFactory cf = CertificateFactory.getInstance("X.509");

    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
    ks.load(null);

    for (int i = 0; i < serverCerts.size(); i++) {
      try (InputStream is = new FileInputStream(serverCerts.get(i))) {
        X509Certificate caCert = (X509Certificate) cf.generateCertificate(is);
        ks.setCertificateEntry("cacrt." + i, caCert);
      }
    }
    return ks;
  }

这将从加载系统证书开始,因此您的客户端仍可用于加载外部托管的映像等。

然后,最重要的是,您可以使用CertificatePinner要求仅将可信任的自签名证书用于您的域。



 类似资料:
  • 问题内容: 我在通过Java与HTTPS站点交互时遇到问题。每次程序运行时,我的程序都使用一个带有不受信任证书的URL。该程序必须在多个系统上运行。目前,我有以下内容: 使用此代码,我可以执行以下操作: 但是,我无法执行以下操作: 当执行executeMethod(postMethod)时,我得到一个SSLHandshakeException,CertPathBuilderException等。

  • 使用Git,有没有办法告诉它接受自签名证书? 我使用https服务器来托管git服务器,但目前证书是自签名的。 当我第一次尝试在那里创建回购时: 我得到的错误:

  • null 有人能帮帮我吗?谢谢。 代码 斯塔克特莱斯

  • 我使用Spring Security使用x.509证书进行身份验证,它仅在浏览器密钥存储库中配置的客户端证书存在于服务器信任存储库中时才工作。 它目前是如何工作的: 我已将SSL客户端身份验证配置为可选(server.SSL.client auth=want,如本文所示) 我已经配置了一个包含所有客户端证书的服务器信任存储。如果客户端提供的证书位于信任存储中,则会创建相互SSL连接 当我的客户端证

  • <?php $http = HttpRequest::newSession(); $response = $http->sslCert('证书路径', 'pem') // 支持PEM、DER和ENG证书 ->get('https://www.baidu.com/'); $content = $response->body(); // 网页源码

  • 伙计们!我正在尝试使用bouncycastle创建X.509证书,它应该由另一个证书签名并存储它的PEM base 64格式。 我已经有了自签名证书(公钥和私钥)。现在我要创建一个新的,并用现有的自签名证书签名。 验证无例外地通过了,这意味着从我的观点来看,它是由Cacert成功签署的: 然后将其解码到PEM base 64: