Java 在Jetty服务器中如何获取需要客户端认证时使用的客户端证书?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20056304/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 22:44:16  来源:igfitidea点击:

In the Jetty server how can I obtain the client certificate used when client authentication is required?

javasslembedded-jettyauthentication

提问by Brian Reinhold

It is very easy to set up an embedded Jetty server that requests client authentication: One just needs to add the statement SslContextFactory.setNeedClientAuth(true); to the ssl context when configuring the server. Any client that has its certificate in the server's truststore will be able to establish a TLS connection to the server.

设置请求客户端身份验证的嵌入式 Jetty 服务器非常容易:只需添加语句 SslContextFactory.setNeedClientAuth(true); 配置服务器时的 ssl 上下文。任何在服务器信任库中拥有其证书的客户端都能够与服务器建立 TLS 连接。

However I need to know which client of all the possible trusted clients is currently making a request; in other words I need to know the client certificate used in this connection, in particular in the handler. Does anyone know how to access this certificate or if it is even possible?

但是,我需要知道所有可能的受信任客户端中的哪个客户端当前正在发出请求;换句话说,我需要知道在此连接中使用的客户端证书,特别是在处理程序中。有谁知道如何访问此证书,或者甚至可能吗?

采纳答案by Joakim Erdfelt

Updated Aug 2019:for Jetty 9.4.20.v20190813 release.

2019 年 8 月更新:适用于 Jetty 9.4.20.v20190813 版本。

The certificates are added to the Requestobjects (such as HttpServletRequest), by a HttpConfigurationCustomizer.

证书由HttpConfiguration Customizer添加到Request对象(例如HttpServletRequest)。

Specifically, the SecureRequestCustomizer.

具体来说,SecureRequestCustomizer

Your code to use this would be as follows (scroll down)...

您使用它的代码如下(向下滚动)...

Server server = new Server();

// === HTTP Configuration ===
HttpConfiguration http_config = new HttpConfiguration();
http_config.setSecureScheme("https");
http_config.setSecurePort(8443);
http_config.setOutputBufferSize(32768);
http_config.setRequestHeaderSize(8192);
http_config.setResponseHeaderSize(8192);
http_config.setSendServerVersion(true);
http_config.setSendDateHeader(false);

// === Add HTTP Connector ===
ServerConnector http = new ServerConnector(server,
    new HttpConnectionFactory(http_config));
http.setPort(8080);
http.setIdleTimeout(30000);
server.addConnector(http);

// === Configure SSL KeyStore, TrustStore, and Ciphers ===
SslContextFactory sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath("/path/to/keystore");
sslContextFactory.setKeyStorePassword("changeme");
sslContextFactory.setKeyManagerPassword("changeme");
sslContextFactory.setTrustStorePath("/path/to/truststore");
sslContextFactory.setTrustStorePassword("changeme");
// OPTIONAL - for client certificate auth (both are not needed)
// sslContextFactory.getWantClientAuth(true)
// sslContextFactory.setNeedClientAuth(true)

// === SSL HTTP Configuration ===
HttpConfiguration https_config = new HttpConfiguration(http_config);
https_config.addCustomizer(new SecureRequestCustomizer()); // <-- HERE

// == Add SSL Connector ===
ServerConnector sslConnector = new ServerConnector(server,
    new SslConnectionFactory(sslContextFactory,"http/1.1"),
    new HttpConnectionFactory(https_config));
sslConnector.setPort(8443);
server.addConnector(sslConnector);

With this SecureRequestCustomizer in place you can access various pieces about the SSL connection from the HttpServletRequest.getAttribute(String)calls using the following attribute names.

使用此 SecureRequestCustomizer,您可以HttpServletRequest.getAttribute(String)使用以下属性名称从调用中访问有关 SSL 连接的各种部分。

javax.servlet.request.X509Certificate

javax.servlet.request.X509Certificate

an array of java.security.cert.X509Certificate[]

java.security.cert.X509Certificate[]数组

javax.servlet.request.cipher_suite

javax.servlet.request.cipher_suite

the String name of the cipher suite. (same as what is returned from javax.net.ssl.SSLSession.getCipherSuite())

密码套件的字符串名称。(与从 返回的内容相同javax.net.ssl.SSLSession.getCipherSuite()

javax.servlet.request.key_size

javax.servlet.request.key_size

Integer of the key length in use

使用的密钥长度的整数

javax.servlet.request.ssl_session_id

javax.servlet.request.ssl_session_id

String representation (hexified) of the active SSL Session ID

活动 SSL 会话 ID 的字符串表示(十六进制)

回答by Will Hartung

There's a standard servlet request property: javax.servlet.request.X509Certificate

有一个标准的 servlet 请求属性:javax.servlet.request.X509Certificate

It returns an array of X509Certificates.

它返回一个 X509Certificates 数组。

We use this to get the name and look up the DN from the cert:

我们使用它来获取名称并从证书中查找 DN:

x509Cert[0].getSubjectX500Principal().getName()