当前位置: 首页 > 知识库问答 >
问题:

实现X509TrustManager-将部分验证传递给现有验证器

咸昊昊
2023-03-14

我需要忽略PKIX路径构建异常

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderExc
ption: unable to find valid certification path to requested target

我知道如何通过编写自己的类来实现X509TrustManager,我总是isServerTrusted返回true

但是,我不想信任所有的服务器

  • 我希望所有的默认验证都能像现在一样为客户端完成
  • 对于服务器,我只想忽略一个特定证书的服务器证书验证,但我想继续验证它,就像目前一样(例如使用cacerts store)

我如何实现这样的目标——即在替换X509TrustFactory对象之前,将部分验证传递给它。

即这就是我想做的

public boolean isServerTrusted(X509Certificate[] chain)
{
    if(chain[0].getIssuerDN().getName().equals("MyTrustedServer") && chain[0].getSubjectDN().getName().equals("MyTrustedServer"))
        return true;

    // else I want to do whatever verification is normally done
}

此外,我不想干扰现有的isClientTrusted验证。

我怎么能这么做呢?

共有3个答案

闻修筠
2023-03-14

虽然这个问题有一个有效的答案,但我想提出一个需要更少自定义代码的替代方案。在这种情况下,当自定义条件为true时,您似乎希望信任对方(客户机或服务器),否则返回到trustmanager的默认验证。您可以尝试以下代码片段:

SSLFactory sslFactory = SSLFactory.builder()
          .withDefaultTrustMaterial() // uses jdk trusted certificates
          .withTrustEnhancer((X509Certificate[] certificateChain, String authType) ->
                  certificateChain[0].getIssuerX500Principal().getName().equals("Foo")
                      && certificateChain[0].getSubjectX500Principal().getName().equals("Bar"))
          .build();

SSLContext sslContext = sslFactory.getSslContext();

它将为您创建一个自定义信任管理器,并在SSLContext中使用它,所以您不需要指定自定义信任管理器。更多信息请参见这里: GitHub-SSLContext Kickstart我正在维护这个库,希望它对其他人有用。

缪茂勋
2023-03-14

您可以从相关的特定证书创建信任管理器,而不是实现信任任何证书的X509TrustManager。从加载证书。p12。jks密钥库或来自的密钥库。crt-文件(在Chrome中,您可以通过单击挂锁并选择证书,将证书从浏览器复制到文件中)。代码比实现自己的X509TrustManager要短:

private static SSLSocketFactory createSSLSocketFactory(File crtFile) throws GeneralSecurityException, IOException {
    SSLContext sslContext = SSLContext.getInstance("SSL");

    // Create a new trust store, use getDefaultType for .jks files or "pkcs12" for .p12 files
    KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
    // You can supply a FileInputStream to a .jks or .p12 file and the keystore password as an alternative to loading the crt file
    trustStore.load(null, null);

    // Read the certificate from disk
    X509Certificate result;
    try (InputStream input = new FileInputStream(crtFile)) {
        result = (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(input);
    }
    // Add it to the trust store
    trustStore.setCertificateEntry(crtFile.getName(), result);

    // Convert the trust store to trust managers
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(trustStore);
    TrustManager[] trustManagers = tmf.getTrustManagers();

    sslContext.init(null, trustManagers, null);
    return sslContext.getSocketFactory();
}

您可以通过调用HttpsURLConnection来使用它。setSSLSocketFactory(createSSLSocketFactory(crtFile))(不过,您可能希望初始化套接字工厂一次并重用它)。

闻人吕恭
2023-03-14

您可以获取现有的默认信任管理器,并使用以下方式将其包装在自己的信任管理器中:

TrustManagerFactory tmf = TrustManagerFactory
        .getInstance(TrustManagerFactory.getDefaultAlgorithm());
// Using null here initialises the TMF with the default trust store.
tmf.init((KeyStore) null);

// Get hold of the default trust manager
X509TrustManager x509Tm = null;
for (TrustManager tm : tmf.getTrustManagers()) {
    if (tm instanceof X509TrustManager) {
        x509Tm = (X509TrustManager) tm;
        break;
    }
}

// Wrap it in your own class.
final X509TrustManager finalTm = x509Tm;
X509TrustManager customTm = new X509TrustManager() {
    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return finalTm.getAcceptedIssuers();
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain,
            String authType) throws CertificateException {
        finalTm.checkServerTrusted(chain, authType);
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain,
            String authType) throws CertificateException {
        finalTm.checkClientTrusted(chain, authType);
    }
};

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { customTm }, null);

// You don't have to set this as the default context,
// it depends on the library you're using.
SSLContext.setDefault(sslContext);

然后,您可以围绕finalTm实现自己的逻辑。checkServerTrusted(链,authType)

但是,您应该确保对要忽略的特定证书进行了例外。

您在下面所做的是允许任何具有这些颁发者DN和主题DN(这并不难伪造)的证书通过:

if(chain[0].getIssuerDN().getName().equals("MyTrustedServer") && chain[0].getSubjectDN().getName().equals("MyTrustedServer"))
    return true;

您可以从已知引用加载X509Certificate实例,并比较链中的实际值。

此外,check ClientTrustedcheck ServerTrusted不是返回truefalse的方法,而是默认情况下将自动成功的方法。如果您期望的证书有问题,请显式抛出证书异常

 类似资料:
  • 本文向大家介绍Java如何实现验证码验证功能,包括了Java如何实现验证码验证功能的使用技巧和注意事项,需要的朋友参考一下 Java如何实现验证码验证功能呢?日常生活中,验证码随处可见,他可以在一定程度上保护账号安全,那么他是怎么实现的呢? Java实现验证码验证功能其实非常简单:用到了一个Graphics类在画板上绘制字母,随机选取一定数量的字母随机生成,然后在画板上随机生成几条干扰线。 首先,

  • 本文向大家介绍JavaScript Canvas实现验证码,包括了JavaScript Canvas实现验证码的使用技巧和注意事项,需要的朋友参考一下 在通常的登录界面我们都可以看到验证码,验证码的作用是检测是不是人在操作,防止机器等非人操作,防止数据库被轻而易举的攻破。 验证码一般用PHP和java等后端语言编写。 但是在前端,用canva或者SVG也可以绘制验证码。 绘制验证码不能是简单的随机

  • 本文向大家介绍javascript实现密码验证,包括了javascript实现密码验证的使用技巧和注意事项,需要的朋友参考一下 本文为大家分享了javascript密码验证的实现方法,欢迎大家阅读。 javascript密码验证代码如下 希望本文对大家学习javascript程序设计有所帮助。

  • 本文向大家介绍Django实现表单验证,包括了Django实现表单验证的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Django实现表单验证的具体代码,供大家参考,具体内容如下 models.py form.py view.py register.html 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。

  • 本文向大家介绍AngularJS实现表单验证,包括了AngularJS实现表单验证的使用技巧和注意事项,需要的朋友参考一下 虽然我不是前端程序员,但明白前端做好验证是多么重要。 因为这样后端就可以多喘口气了,而且相比后端什么的果然还是前端可以提高用户的幸福感。 AngularJS提供了很方便的表单验证功能,在此记录一番。 首先从下面这段代码开始 input标签的一些验证选项,通常和HTML5标记搭

  • 本文向大家介绍PHP实现验证码校验功能,包括了PHP实现验证码校验功能的使用技巧和注意事项,需要的朋友参考一下 验证码的校验是利用PHP中的 SESSION功能来实现。 在最顶端声明函数 session_start(); 告诉服务器我们要用这个函数的功能。 接下来我们用到的就是验证码实现的代码。这里用英文数字的代码为例。 然后在验证码实现之前声明一个空变量,用来存放验证码。 用 POST 方式来接