Как получить сертификат клиента на причальном сервере при аутентификации

После установки встроенного сервера Jetty, который запрашивает аутентификацию клиента путем установки SslContextFactory.setNeedClientAuth (true), как я могу получить информацию о сертификате клиента, когда клиент подключается к серверу причала в обоих случаях, аутентификация прошла успешно и не удалась?

Я прочитал это ссылка, но я думаю, что это применимо только для успешной аутентификации. SecureRequestCustomizer.customize(...), похоже, выполняется только после успешной аутентификации информации о сертификате клиента.

Но вот что мне интересно, есть ли какой-либо подход для получения информации о сертификате клиента, когда причальный сервер выполняет аутентификацию, независимо от того, успешна она или нет. Затем я могу получить информацию о сертификате клиента, даже если этому клиенту не доверяет сервер причала.


person siaodi    schedule 13.08.2020    source источник


Ответы (1)


Добро пожаловать в stackoverflow.

Если у вас установлен SslContextFactory.setNeedClientAuth(true), это означает, что вы устанавливаете уровень Java javax.net.ssl.SSLParameters.setNeedClientAuth(true).

Это влияет на согласование TLS / SSL на уровне Java новых подключений и заставляет их требовать действительный сертификат клиента.

Если это не удается, соединение разрывается самой Java на уровне подтверждения TLS / SSL, и клиент даже не отправляет HTTP-запрос, и Jetty не участвует в этом определении.

Как вы, несомненно, уже заметили, соединение, которое не прошло проверку подлинности клиента уровня TLS / SSL, не обрабатывается в SecureRequestCustomizer.

Если вы хотите, чтобы успешные и неудачные клиенты прошли уровень подтверждения TLS / SSL и достигли ваших различных обработчиков HTTP, вам придется отключить параметр SslContextFactory.setNeedClientAuth(true). Но это означает, что нет аутентификации сертификата клиента, выполняемой уровнями TLS / SSL Java JVM, и теперь вы можете выполнить те же проверки в своем собственном коде. Это не сработает.

Итак, у вас есть выбор ...

  1. setNeedClientAuth(true) - Соединение аутентифицировано, разрывается, если сертификат клиента не прошел. Клиент не создает HTTP-запросов.
  2. setNeedClientAuth(false) - Все соединения проходят успешно, аутентификация не выполняется, что приводит к появлению HTTP-запросов, которые затем можно обрабатывать.

Если вам нужен пункт 1, но пункт 2 не подходит, подумайте об использовании org.eclipse.jetty.io.ssl.SslHandshakeListener и просто обратите внимание на результаты успеха / неудачи.

Создайте свою собственную реализацию этого прослушивателя и добавьте его как bean-компонент в ваши серверные коннекторы. Вам будет передан активный javax.net.ssl.SSLEngine для этого источника событий, где вы можете запросить различные подробности, которые вам нужны для неудачного соединения (вы даже можете получить IP-информацию клиента, который попытался установить соединение)

person Joakim Erdfelt    schedule 17.08.2020
comment
Большое спасибо, это то, что я хочу. - person siaodi; 20.08.2020
comment
Привет @Joakim, я пробовал, но когда ssl-рукопожатие не удалось, я не могу получить никакой информации от SSLEngine. Я получаю SSLSession, SSLSession session = event.getSSLEngine().getSession();, но когда я получаю другую информацию с session.getPeerCertificates(), session.getPeerCertificateChain(), все это бросает javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated. Когда рукопожатие ssl в порядке, я могу получить информацию о сертификатах двумя вышеуказанными способами. Вы что-нибудь знаете об этом. Большое спасибо - person siaodi; 11.09.2020
comment
Имейте в виду, что session.getPeerCertificateChain() устарел, используйте рекомендуемые альтернативы, указанные в javadoc, и обратите внимание на javadoc по рекомендуемым путям о том, что означает SSLPeerUnverifiedException, особенно в отношении определенных функций наборов шифров. - person Joakim Erdfelt; 11.09.2020
comment
Я проверил, использовал правильный шифр и попробовал getPeerCertificates(), но сертификатов все равно не найдено. В документации этого метода сказано, что SSLPeerUnverifiedException будет выброшено if the peer's identity has not been verified. Поэтому я боюсь, что не могу получить идентификацию однорангового узла, когда аутентификация не удалась. - person siaodi; 16.09.2020
comment
Я попытался инициировать настройку SslContextFactory с SSLContex, инициализировав себя с помощью X509TrustManager и X509TrustManager.checkServerTrusted(X509Certificate[] var1, String var2) переопределения, в этом методе я могу напрямую распечатать информацию о сертификатах, независимо от того, аутентифицирован ли одноранговый узел или нет. К счастью, это работает. Но предвидите ли вы риск с самодельным SSLContext в Jetty? - person siaodi; 16.09.2020