Jetty:如何验证应用程序代码中的 SSL 客户端证书?
Jetty: How to validate SSL client certs in application code?
我有一个多租户网络服务,我想使用相互 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 连接将被拒绝。
虽然 TrustAll
似乎是可能的解决方案,但只有在未提供 TrustStore and 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;
}
}
使用:
- 按照 Jetty 文档配置 SSL/TLS 客户端身份验证
- 针对 Jetty 编译上面的代码 9.x
- 在`$jetty.home/lib/ext'中安装 jar
编辑$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">
二。添加 <Set name="TrustAll">TRUE</Set>
作为 child of <Configure id="sslContextFactory">
为什么? JSSE 已经验证了它。您只需检查该用户的授权。当您访问证书时,它已经过完整性、不过期和信任锚定验证,因此您可以相信它的 SubjectDN 指的是它所说的谁,所以您所要做的就是决定SubjectDN 有什么角色,如果有的话。
我有一个多租户网络服务,我想使用相互 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 连接将被拒绝。
虽然 TrustAll
似乎是可能的解决方案,但只有在未提供 TrustStore and 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;
}
}
使用:
- 按照 Jetty 文档配置 SSL/TLS 客户端身份验证
- 针对 Jetty 编译上面的代码 9.x
- 在`$jetty.home/lib/ext'中安装 jar
编辑
$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">
二。添加
<Set name="TrustAll">TRUE</Set>
作为 child of<Configure id="sslContextFactory">
为什么? JSSE 已经验证了它。您只需检查该用户的授权。当您访问证书时,它已经过完整性、不过期和信任锚定验证,因此您可以相信它的 SubjectDN 指的是它所说的谁,所以您所要做的就是决定SubjectDN 有什么角色,如果有的话。