【问题标题】:Jetty: How to validate SSL client certs in application code?Jetty:如何在应用程序代码中验证 SSL 客户端证书?
【发布时间】:2017-10-18 15:29:48
【问题描述】:

我有一个多租户网络服务,我想使用相互 SSL/TLS 身份验证以及用户身份验证。这意味着我需要解析用户和用户允许的证书,这只能发生在 SSL 连接建立之后。然后,我将使用PKIXCertPathBuilderResult 使用请求中传递的客户端证书来验证信任链。

在带有 openssl 连接器的 Tomcat 中,可以使用 optional_no_ca 模式,它请求客户端证书但不验证它。

使用 Jetty 9.x,我尝试配置以下 SslContextFactory 选项无济于事:

  • ValidateCerts=false
  • ValidatePeerCerts=false
  • TrustAll=true

如何在 Jetty 9.x 中实现这一点?

2019 年编辑:要求是要求访问系统的所有客户端设备提供 SSL 证书。然后,应用程序将执行证书链和其他证书属性的验证,该应用程序还能够从外部源查找丢失的证书根。 这与规范相反——通常,应用程序服务器将在 SSL 连接设置期间使用预先配置的已知受信任 CA 的静态列表执行证书链验证。如果无法找到信任,则拒绝 SSL 连接。

【问题讨论】:

    标签: java ssl jetty jetty-9 ssl-client-authentication


    【解决方案1】:

    虽然TrustAll 似乎是可能的解决方案,但它仅在没有给出 TrustStore KeyStore 的情况下才有效。然后您无法使用常规客户端进行连接,因为服务器在握手期间没有证书可提供。

    要获得合理的 trustAll 模式,唯一的选择似乎是扩展 SslContextFactory

    package media.alu.jetty;
    /**
     * SslContextFactoryRelaxed is used to configure SSL connectors
     * as well as HttpClient. It holds all SSL parameters and
     * creates SSL context based on these parameters to be
     * used by the SSL connectors.
     *
     * TrustAll really means trustAll!
     */
    @ManagedObject
    public class SslContextFactoryRelaxed extends SslContextFactory
    {
        private String _keyManagerFactoryAlgorithm = DEFAULT_KEYMANAGERFACTORY_ALGORITHM;
        private String _trustManagerFactoryAlgorithm = DEFAULT_TRUSTMANAGERFACTORY_ALGORITHM;
    
        @Override
        protected TrustManager[] getTrustManagers(KeyStore trustStore, Collection<? extends CRL> crls) throws Exception
        {
            TrustManager[] managers = null;
            if (trustStore != null)
            {
                if (isTrustAll()) {
                    managers = TRUST_ALL_CERTS;
                }
    
                // Revocation checking is only supported for PKIX algorithm
                else if (isValidatePeerCerts() && "PKIX".equalsIgnoreCase(getTrustManagerFactoryAlgorithm()))
                {
                    PKIXBuilderParameters pbParams = newPKIXBuilderParameters(trustStore, crls);
    
                    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
                    trustManagerFactory.init(new CertPathTrustManagerParameters(pbParams));
    
                    managers = trustManagerFactory.getTrustManagers();
                }
                else
                {
                    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
                    trustManagerFactory.init(trustStore);
    
                    managers = trustManagerFactory.getTrustManagers();
                }
            }
    
            return managers;
        }
    
    }
    

    使用方法:

    1. 按照 Jetty 文档配置 SSL/TLS 和客户端身份验证
    2. 针对 Jetty 9.x 编译以上代码
    3. 在 `$jetty.home/lib/ext' 中安装 jar
    4. 编辑$jetty.home/etc/jetty-ssl-context.xml

      我。变化:

      <Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
      

      到:

      <Configure id="sslContextFactory" class="media.alu.jetty.SslContextFactoryRelaxed">
      

      二。将&lt;Set name="TrustAll"&gt;TRUE&lt;/Set&gt; 添加为&lt;Configure id="sslContextFactory"&gt; 的子级

    【讨论】:

      【解决方案2】:

      为什么? JSSE 已经对其进行了验证。您需要做的就是检查该用户的授权。当您访问证书时,它已经通过完整性、永不过期和信任锚定的验证,因此您可以相信它的 SubjectDN 指的是它所说的对象,所以您所要做的就是决定SubjectDN 具有哪些角色(如果有)。

      【讨论】:

      • 谢谢,您让我想了想,但我没有对所有用户通用的 CA - 每组用户都将由不同的 CA 签名。然后我必须维护一个包含所有已知 CA 的 JKS。
      • 没关系。您将身份验证与授权混为一谈。您应该为所有客户端使用相同的信任库,然后才授权
      • 我没有将身份验证和授权混为一谈。用户提供凭证数据以对系统进行身份验证和授权。用户通过身份验证和授权后,我需要授权他们的设备与系统一起使用。在大型集群全局分布式环境中的文件系统上维护一个不断变化的 JKS 文件是一个 PITA,所以它确实很重要。此外,JSSE 中没有什么神奇的东西可以定义这一点 - 这是为每个碰巧执行它的实现定制的 SSL 连接器。
      • 1.你是。 TLS 认证;申请授权。 2. 如果 CA 受默认 cacerts 信任,则维护为零,如果不是,您只需维护 CA 中的更改,这应该很少发生:CA 证书运行数十年。 3. 肯定有。 JSSE 做到了这一切。连接器仅使用 JSSE。 JSSE 是所有信任管理和 PKIX 路径构建所在的位置。
      • 1.用户凭据(用户名/密码)对用户进行身份验证,设备身份验证和授权稍后在应用程序中进行。对我来说最重要的是用户 a + a。 2. 阅读评论 #1 - “我没有所有用户通用的 CA”。这些是私有 CA,因此不会出现在 cacerts 中(Verisign 等人甚至签署客户端证书吗?!)。 3. 连接器默认使用 SunJSSE,它具有一些用于建立信任的默认机制。这只是一种实现。那么谁说设备身份验证和授权必须在连接器级别进行?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-24
      • 1970-01-01
      • 1970-01-01
      • 2013-05-29
      • 2017-05-18
      • 2015-08-07
      相关资源
      最近更新 更多