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

带有主机名验证的SSLContext

黄骏喆
2023-03-14

在测试我的客户机-服务器分布式系统时,我最初惊讶地得知TLS的默认JSSE实现不进行主机名验证。我在这个问题中尝试了公认的答案,但我的用例有点不同。我使用RabbitMQ的连接工厂,它抽象了SSLSocket的构造。我只是为连接工厂提供了一个SSLContext。我确实找到了很多关于HTTPS的信息,甚至还有一些其他协议,但并不是总能使用的通用协议,即使是自定义协议。

但是,除了使用X509ExtendedTrustManager之外,关于创建域验证SSLContext并没有太多的内容。在调试时,我可以看到

TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init((KeyStore) null);
tmf.getTrustManagers();
final TrustManager[] trustManagers = tmf.getTrustManagers();
X509ExtendedTrustManager x509ExtendedTrustManager = new X509ExtendedTrustManager() {
    @Override
    public void checkClientTrusted(X509Certificate[] x509Certificates, String s, Socket socket) throws CertificateException {
        checkClientTrusted(x509Certificates, s);
    }

    @Override
    public void checkServerTrusted(X509Certificate[] x509Certificates, String s, Socket socket) throws CertificateException {
        checkServerTrusted(x509Certificates, s);
    }

    @Override
    public void checkClientTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) throws CertificateException {
        checkClientTrusted(x509Certificates, s);
    }

    @Override
    public void checkServerTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) throws CertificateException {
        checkServerTrusted(x509Certificates, s);
    }

    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
        for (TrustManager trustManager : trustManagers)
            ((X509TrustManager)trustManager).checkClientTrusted(x509Certificates, s);
    }

    public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
        for (TrustManager trustManager : trustManagers)
            ((X509TrustManager)trustManager).checkServerTrusted(x509Certificates, s);

        for (X509Certificate x509Certificate : x509Certificates) {
            Collection<List<?>> alternativeNameCollection = x509Certificate.getSubjectAlternativeNames();
            if (alternativeNameCollection != null) {
                for (List alternativeNames : alternativeNameCollection) {
                    if (alternativeNames.get(1).equals(host))
                        return;
                }
            }
        }

        throw new CertificateException("Certificate hostname and requested hostname don't match");
    }

    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
};

这终于奏效了。但我不敢相信没有一个更干净的方法来做这件事。基本上,我要找的是一些标准的东西,因为我认为我所做的也是相当标准的。我读过关于hostNameVerifier的文章,但是有没有一种方法可以在SSLContext中使用它而不使用HTTPS呢?是否存在X509ExtendedTrustManager的主机名验证实现?我肯定我在重新发明已经写好的东西。

编辑:这是一个很好的,工作的例子。但仍然是自定义代码。

编辑2:RabbitMQ仍然存在问题,因为RabbitMQ解析DNS并将IP地址传递给验证器,这当然总是失败。因此X509ExtendedTrustManager似乎仍然是可行的方法。

共有1个答案

章建木
2023-03-14

主机名验证不是SSL的一部分。它是HTTPS的一部分。您正在调查错误的层和错误的API。您应该查看HTTPURLConnectionHostNameVerifier

 类似资料:
  • 问题内容: 我正在开发一个Android应用,并且需要访问一个HTTPS地址。我正在使用Volley来请求我的数据,但现在却收到此错误 要获得SSL工厂,我需要这样做: 队列初始化: 这是堆栈跟踪: 我搜索了错误,但没有找到适合我的情况的内容。谁能帮我? 问题答案: 让我们假设你的服务器的应用程序是具有服务器证书中的服务器机内托管的,例如。然后,在验证方法内部,您可以验证。 您可以通过以下链接阅读

  • 问题内容: 跟进正则表达式以匹配主机名或IP地址? 并使用对有效主机名的限制作为参考,在Python中匹配/验证主机名/ fqdn(完全限定域名)的最易读,简洁的方法是什么?我在下面的尝试中已经回答过,欢迎改进。 问题答案: import re def is_valid_hostname(hostname): if len(hostname) > 255: return False if host

  • 我有一个使用Spring Boot实现的应用程序,我在其中使用Spring Security进行身份验证。我已经有了“基于令牌的”身份验证,其中要求客户端检索令牌,然后在后续请求中使用该令牌进行身份验证。 我希望对此进行增强,以便令牌可以被限制为特定主机名,因此只能用于来自该主机的请求。这类似于谷歌地图API对其API密钥所做的操作,可以通过IP或主机名来限制它们。 以下是我实现的代码,用于尝试检

  • 我正在esp32上实现一个websocket服务器,并且在android studio Simulator上运行的应用程序上使用okhttp lib。 我正在使用由openssl命令生成的自分配证书:openssl req-newkey rsa:2048-nodes-keyout prvtkey.pem-x509-days 3650-out cacert.pem-subj“/cn=esp32 HT

  • 我们使用Spring SAML扩展将Salesforce设置为IDP,我们的应用程序是SP。但我们得到错误“SSL对等方未能通过名称:null的主机名验证” 下面是我们的 SAML 配置类。 我们尝试了将“Spring Security SAML HTTPS链接到另一个页面”的建议,其中1)禁用主机名验证,或2)注释掉Bean“TLSProtocolConfigurer”,并将Salesforce

  • 问题内容: 我在Go中编写自己的ReverseProxy。ReverseProxy应该连接我的go-webserver和apache2 webserver。但是,当我在另一个IP地址上运行反向代理时,然后在我的Apache2 Web服务器上,当反向代理将请求发送到apache时,我的apache-logfile中出现以下错误。 我的反向代理和apache-webserver在https上运行。 这