2014-06-22 1 views
5

Мой клиент реализует двухстороннюю SSL следующим образом:GetAttribute ("javax.servlet.request.X509Certificate") не установлен (Spring, CXF, Jetty, JAX-RSv1.1)

 

    private final static String KEYSTORE = "/security/client.jks"; 
    private final static String KEYSTORE_PASSWORD = "secret"; 
    private final static String KEYSTORE_TYPE = "JKS"; 
    private final static String TRUSTSTORE = "/security/certificates.jks"; 
    private final static String TRUSTSTORE_PASSWORD = "secret"; 
    private final static String TRUSTSTORE_TYPE = "JKS"; 
    ... 
    KeyStore keystore = KeyStore.getInstance(KEYSTORE_TYPE); 
    FileInputStream keystoreInput = new FileInputStream(new File(KEYSTORE)); 
    keystore.load(keystoreInput, KEYSTORE_PASSWORD.toCharArray()); 
    KeyStore truststore = KeyStore.getInstance(TRUSTSTORE_TYPE); 
    FileInputStream truststoreIs = new FileInputStream(new File(TRUSTSTORE)); 
    truststore.load(truststoreIs, TRUSTSTORE_PASSWORD.toCharArray()); 
    SSLSocketFactory socketFactory = new SSLSocketFactory(keystore, KEYSTORE_PASSWORD, truststore); 
    Scheme scheme = new Scheme("https", 8543, socketFactory); 
    SchemeRegistry registry = new SchemeRegistry(); 
    registry.register(scheme); 
    ClientConnectionManager ccm = new PoolingClientConnectionManager(registry); 
    httpclient = new DefaultHttpClient(ccm); 
    HttpResponse response = null; 
    HttpGet httpget = new HttpGet("https://mylocalhost.com:8543/test"); 
    response = httpclient.execute(httpget); 
    ... 

И Я пытаюсь получить сертификат X.509 со стороны сервера от клиента через javax.servlet.http.HttpServletRequest.getAttribute («javax.servlet.request.X509Certificate»), как описано здесь: http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/ServletRequest.html#getAttribute%28java.lang.String%29.

Я получаю HttpServletRequest на стороне сервера с помощью:
HttpServletRequest ServletRequest = (HttpServletRequest) msg.get ("HTTP.REQUEST"); через метод handleMessage (Message msg) моего класса перехватчика, который расширяет AbstractPhaseInterceptor < Сообщение >. Я должен использовать JAX-RS 1.1.1 со стороны сервера из-за некоторых зависимостей Maven, которые мне не разрешают изменять, и поэтому я не могу использовать ContainerRequestFilter (поддерживается JAX-RS 2.0).

Моя проблема заключается в том, что getAttribute ("javax.servlet.request.X509Certificate") со стороны сервера возвращает null все время. Если я проверю трафик между сервером и клиентом, я вижу, что сертификат с сервера отправляется клиенту, и это рукопожатие работает. Но я не вижу, что клиентский сертификат отправляется на сервер, и я думаю, что это причина, по которой getAttribute("javax.servlet.request.X509Certificate") возвращает null. Кто-нибудь знает, как я могу решить эту проблему? Я уже пробовал некоторые другие реализации на стороне клиента, но без изменений.

Что я делаю неправильно? Спасибо заранее!

Дополнительная информация: Я видел на стороне сервера, что javax.servlet.request.ssl_session_id, javax.servlet.request.key_size и javax.servlet.request.cipher_suite установлены, но ключ javax.servlet.request. X509Certificate не установлен. Я использую Jetty Server 8.1.15, Apache CXF 2.7.x и JAX-RS 1.1.1. Я пробовал с конфигурацией Jetty через http://cxf.apache.org/docs/jetty-configuration.html и http://cxf.apache.org/docs/secure-jax-rs-services.html#SecureJAX-RSServices-Configuringendpoints, атрибут все еще не установлен.

+0

Название предполагает, что вы хотите подписать запрос HTTPS, содержимое вопроса выглядит так, будто вы пытаетесь использовать клиент-сертификат. Это разные вещи. – Bruno

+0

Привет, Бруно, клиент должен быть аутентифицирован сервером через сертификат X.509. Я хочу извлечь сертификат X.509, чтобы сервер мог сравнить сертификат с его доверительным магазином. Я не мог узнать, есть ли проблема на стороне клиента или на стороне сервера. Поэтому мой вопрос может быть немного неспецифичным. Пожалуйста, несите меня, я новичок здесь. Большое спасибо! Я добавил дополнительную информацию выше. –

ответ

13

Проблема решена. Это не было проблемой в коде, это была проблема с сертификатом. Моя проблема заключалась в том, что я был новичком в отношении сертификатов X509, это была проблема рукопожатия между сервером и клиентом. В этом случае мне помог только отладка SSL/Handshake. Журнал отладки сказал, что сервер только принимал клиентские сертификаты от определенного ЦС, сервер сообщил клиенту требуемый ЦС в запросе сертификата во время сообщения ServerHello. Поскольку у Клиента не было сертификата от этого ЦС, он ничего не отправил, и соединение между клиентом и сервером было закрыто тогда, в результате чего javax.servlet.request.X509Certificate не был установлен.

Для всех остальных, кто может присоединиться к той же проблемой когда-то (что, как представляется, проблема конфигурации общего SSL в отношении к IBM, как это упомянуто в первой ссылке ниже), следующие источники помогли мне:
- http://www-01.ibm.com/support/docview.wss?uid=swg27038122&aid=1 (страницы 16 и 17)
- http://java.dzone.com/articles/how-analyze-java-ssl-errors (показывает, как рукопожатие должно выглядеть)
- need help Debugging SSL handshake in tomcat (показывает, как отлаживать ошибки SSL в Java)
- https://thomas-leister.de/internet/eigene-openssl-certificate-authority-ca-erstellen-und-zertifikate-signieren/ (на немецком языке, но, возможно, вы можете найти английский эквивалент)
- https://access.redhat.com/site/documentation/en-US/Red_Hat_JBoss_Fuse/6.0/html/Web_Services_Security_Guide/files/i382674.html (продолжение немецкого искусства icle)
- http://www.webfarmr.eu/2010/04/import-pkcs12-private-keys-into-jks-keystores-using-java-keytool/ (как создать хранилище ключей и доверенных сертификатов)

После создания собственного центра сертификации, сертификат сервера и клиента и после создания хранилища ключей и доверенных сертификатов для обоих, атрибут был установлен в настоящее время:
- Here15_1: javax.servlet.request.X509Certificate
- Here16_2: класс [Ljava.security.cert.X509Certificate;
- Here16_3: [Ljava.security.cert.X509Certificate; @ 43b8f002
Код сервера также может извлекать информацию о сертификате клиента.

+0

Примечание: Я должен добавить, что «javax.net.ssl.SSLHandshakeException: null cert chain» вызывается только сервером, если флаги ... ... и ... ... установлены на true со стороны сервера. Если needClientAuth установлено в false, клиент и сервер не будут вызывать сообщения об ошибках, поскольку тогда сертификат клиента не требуется. –

Смежные вопросы