Подтвердить что ты не робот

Взаимная аутентификация с веб-сервисами

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

Во-первых, есть ли какие-либо ресурсы, о которых кто-либо знает, могут помочь мне в этом? Я искал довольно долго и ничего не нашел. Любые другие советы, которые могут дать мне о том, как это сделать?

Во-вторых, я считаю, что моим самым большим препятствием является отсутствие понимания того, как обрабатывать сертификаты. Как мне согласовать прием ключа сервера и представление моего собственного ключа на сервер? Это в Java.

4b9b3361

Ответ 1

Я потратил много времени на это, но я наконец нашел пример, который действительно работает. Это Glassfish и Netbeans, но я думаю, вы могли бы заставить его работать в других средах (например, Eclipse и Tomcat), если вы играли с ним.

http://java.sun.com/webservices/reference/tutorials/wsit/doc/WSIT_Security9.html#wp162511

Проблема, которую я обнаружил, заключается в том, когда вы хотите использовать свои собственные сертификаты, а не те, которые поставляются предварительно с помощью стеклянной рыбы.

Примечание. Я не эксперт по безопасности. Не развертывайте это в рабочей среде!

Для этого я использую NetBeans 6.9, JDK 1.6, GlassFish 3.0.1 и OpenSSL v1.0 (я использую неофициальные двоичные файлы Win32)

# Create the CA
mkdir ca server client
cd ca
openssl req -new -x509 -days 3650 -extensions v3_ca -keyout ca.key -out ca.pem
echo 02 > serial.txt
cd ..

# Creating the Server Keystore

openssl req -days 3650 -newkey rsa:1024 -keyout server/server.key -out server/server.req
openssl x509 -extensions usr_cert -extfile C:\testbed\OpenSSL-Win32\bin\openssl.cfg -CA ca/ca.pem -CAkey ca/ca.key -CAserial ca/serial.txt -req -in server/server.req -out server/server.crt
openssl pkcs12 -export -inkey server/server.key -in server/server.crt -out server/server.p12 -name server
keytool -importkeystore -destkeystore server/server.jks -deststoretype jks -srckeystore server/server.p12 -srcstoretype pkcs12
keytool -exportcert -alias server -keystore server/server.jks -file server/server.cer

# Create the Client Keystore

openssl req -days 3650 -newkey rsa:1024 -keyout client/client1.key -out client/client1.req
openssl x509 -extensions usr_cert -extfile C:\testbed\OpenSSL-Win32\bin\openssl.cfg -CA ca/ca.pem -CAkey ca/ca.key -CAserial ca/serial.txt -req -in client/client1.req -out client/client1.crt
openssl pkcs12 -export -inkey client/client1.key -in client/client1.crt -out client/client1.p12 -name client1
keytool -importkeystore -destkeystore client/client1.jks -deststoretype jks -srckeystore client/client1.p12 -srcstoretype pkcs12
keytool -exportcert -alias client1 -keystore client/client1.jks -file client/client1.cer

# Import public keys and certificates into each others keystores

keytool -import -noprompt -trustcacerts -alias client1 -file client/client1.cer -keystore server/server.jks
keytool -import -noprompt -trustcacerts -alias server -file server/server.cer -keystore client/client1.jks
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore server/server.jks
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore client/client1.jks
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\cacerts.jks"
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore "C:\Program Files\Java\jdk1.6\jre\lib\security\cacerts"
move "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks" "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks.backup"
copy server\server.jks "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks"

В консоли администратора GlassFish включите Security на своем http-прослушивателе, отметьте поля SSL3, TLS и Client Authentication, установите имя NickName для сервера, хранилище ключей в config\keystore.jks, хранилище Trust для конфигурации \keystore.jks, алгоритм Trust для PKIX и оставить максимальную длину сертификата в 5.

В NetBeans создайте новый проект веб-приложения. В этом случае создайте новую веб-службу.

Код моей веб-службы выглядел так:

@WebService()
public class ListProducts {

  @Resource WebServiceContext context;

  @WebMethod(operationName = "listProducts")
  public String listProducts() {
    return context.getUserPrincipal().toString();
  }

}

Щелкните правой кнопкой мыши веб-службу и выберите "Редактировать атрибуты веб-службы". Отметьте поле "Безопасная услуга" и выберите "Безопасность взаимных сертификатов" в качестве механизма безопасности. Нажмите кнопку "Настроить..." и отметьте поле "Шифровать подпись". Теперь отмените флажок Использовать стандартные значения по умолчанию, а затем нажмите кнопку Keystore. Задайте местоположение хранилища server.jks и выберите псевдоним server. Сделайте то же самое для конфигурации Truststore (хотя вам здесь не нужно выбирать псевдоним).

Импортируйте клиентский сертификат client1.p12 в свой браузер. Разверните свою веб-службу в Glassfish. Откройте веб-службу в браузере и перейдите к развернутому WSDL через HTTPS. Загрузите WSDL и любые другие схемы. Переименуйте любые ссылочные схемы в локальные копии, чтобы при использовании WSDL2Java NetBeans не будет использовать удаленные ресурсы. (Этот параграф связан с тем, что вы ограничили WSDL клиентами с утвержденным сертификатом, но NetBeans не может получить его удаленно, поскольку он не имеет доступа к соответствующему сертификату).

Создайте новый Java-проект. Создайте нового клиента веб-службы. При появлении запроса укажите NetBeans в сохраненный файл WSDL. Импортируйте файлы библиотеки METRO2.0 (C:\Program Files\Netbeans 6.9\enterprise\modules\ext\metr\webservices-*.jar). Мой код выглядел так:

public static void main(String[] args) {
  System.getProperties().put("javax.net.ssl.keyStore", "C:\\NetBeansProjects\\security-04\\ssl\\client\\client1.jks");
  System.getProperties().put("javax.net.ssl.keyStorePassword", "changeit");
  System.getProperties().put("javax.net.ssl.trustStore", "C:\\NetBeansProjects\\security-04\\ssl\\client\\client1.jks");
  System.getProperties().put("javax.net.ssl.trustStorePassword", "changeit");
  System.out.println(new ListProductsService().getListProductsPort().listProducts());
}

Скопируйте webservices-api.jar в каталог Java\jdk1.6\jre\lib\endorsed. Щелкните правой кнопкой мыши ссылку на веб-службу и выберите "Редактировать атрибуты веб-службы". Задайте расположение хранилища ключей для client1.jks и установите псевдоним client1. Задайте местоположение truststore клиенту1.jks и установите псевдоним server.

Надеюсь, теперь вы можете запустить своего клиента, и вы должны увидеть вывод следующим образом: EMAILADD[email protected], CN=Bob Smith, OU=Something, O=SomethingElse, L=AnyTown, ST=AnyState, C=US

Ответ 2

Для взаимной аутентификации с помощью SSL (aka two-way SSL) за пределами браузера вам понадобится... Ну, на самом деле, сначала посмотрим, что вам нужно для одностороннего SSL:

  • Хранилище сервера
  • Клиентский магазин доверия

Хранилище ключей сервера содержит сервер (возможно, самозаверяющий) сертификат и закрытый ключ. Этот магазин используется сервером для подписывания сообщений и возврата учетных данных клиенту.

Консоль доверия клиентов содержит серверный (самозаверяющий) сертификат (извлеченный из хранилища ключей сервера в автономный сертификат без личного ключа сервера). Это необходимо, если сертификат не подписан доверенным ЦС, для которого у вас уже есть сертификат в доверенном магазине в комплекте с JRE. Этот шаг позволяет создать цепочку доверия.

С этим вы можете реализовать односторонний SSL (традиционный вариант использования).

Чтобы реализовать двусторонний SSL, вам нужно сделать эту настройку "симметричной", поэтому нам нужно добавить:

  • Клиентское хранилище
  • Сервер доверия

Клиентское хранилище ключей содержит клиентский (возможно, самозаверяющий) сертификат и закрытый ключ. Это хранилище используется клиентом с той же целью, что и серверное хранилище ключей, то есть отправлять клиентские учетные данные на сервер во время взаимного подтверждения аутентификации TLS.

Серверный сервер доверия содержит клиентские (самозаверяющие) автономные сертификаты (извлеченные из хранилища ключей клиентов в автономные сертификаты без закрытого ключа клиентов). Это необходимо по тем же причинам, что упоминалось ранее.

Некоторые ресурсы, которые помогут вам создать все это и реализовать окончательные решения:

Ответ 3

Если библиотека веб-сервисов использует стандартный класс java.net.URL в качестве HTTP-клиента, вы можете установить некоторые свойства и двухстороннюю аутентификация будет выполняться с помощью встроенной поддержки HTTPS.

необходимые свойства:

  • javax.net.ssl.trustStore: содержит корневые сертификаты CA
  • javax.net.ssl.keyStore: содержит сертификат клиента и закрытый ключ
  • javax.net.ssl.keyStorePassword: пароль, защищающий закрытый ключ клиента

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

Ответ 4

Простой рецепт приведен в этой записи в блоге.

Но я думаю, что реальный ответ может зависеть от того, какие Java-API вы используете для реализации ваших клиентских HTTP-взаимодействий. Например, похоже, что вы делаете несколько иначе с помощью JAX-RPC.