简体   繁体   中英

Jetty: How to validate SSL client certs in application code?

I have a multi-tenant webservice which I want to use mutual SSL/TLS authentication as well as user authentication. This means that I need to resolve the user and the user's allowed certs, which can only occur after the SSL connection has been established. I will then use PKIXCertPathBuilderResult to valid the trust chain using the client certs passed in the request.

In Tomcat with the openssl connector, it's possible to use optional_no_ca mode, which requests a client cert but does not validate it.

With Jetty 9.x, I've tried configuring the following SslContextFactory options to no avail:

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

How can this be achieved in Jetty 9.x?

Edit 2019: The requirement was to demand an SSL certificate from all client devices accessing the system. The validation of the certificate chain and other certificate attributes would then be performed by the application, which also has the ability to lookup missing cert roots from external sources. This is in contrast to the norm - typically, application servers would perform cert-chain validation during the SSL connection setup using a pre-configured static list of known trusted CAs. If trust can not be found, the SSL connection is rejected.

While TrustAll seems to be the likely solution, it only works if no TrustStore and KeyStore is given. Then you can't connect using a regular client as the server has no certificate to give during the handshake.

To get a sensible trustAll mode, the only options seems to be to extend 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;
    }

}

To use:

  1. Follow Jetty documentation to configure SSL/TLS with client authentication
  2. Compile code above against Jetty 9.x
  3. Install jar in `$jetty.home/lib/ext'
  4. Edit $jetty.home/etc/jetty-ssl-context.xml

    i. Change:

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

    to:

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

    ii. Add <Set name="TrustAll">TRUE</Set> as child of <Configure id="sslContextFactory">

Why? JSSE already validates it. All you need to to is check the authorization of that user. By the time you get access to the certificate, it is already validated for integrity, non-expiry, and trust-anchoring, so you can believe that its SubjectDN refers to who it says it refers to, so all you have to do is decide what roles that SubjectDN has, if any.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM