Автор оригинала: Krzysztof Woyke.
1. Обзор
В этой статье мы сосредоточимся на основных случаях использования для проверки подлинности сертификата X.509 – проверка личности одноранговой при использовании протокола HTTPS (HTTP по SSL).
Проще говоря – в то время как безопасное соединение установлено, клиент проверяет сервер в соответствии с его сертификатом (выданным доверенным органом сертификата).
Но помимо этого, X.509 весной безопасности могут быть использованы для проверить личность клиента на сервере при подключении. Это называется “взаимная аутентификация”, и мы будем смотреть на то, как это делается здесь.
Наконец, мы будем касаться когда имеет смысл использовать этот вид проверки подлинности .
Чтобы продемонстрировать проверку сервера, мы создадим простое веб-приложение и установим пользовательский сертификат в браузере.
Более того, для взаимная аутентификация , мы создадим клиентский сертификат и изменим наш сервер, чтобы разрешить только проверенных клиентов.
Настоятельно рекомендуется следовать учебник шаг за шагом и создавать сертификаты, а также keystore и truststore, самостоятельно, в соответствии с инструкциями, представленными в следующих разделах. Тем не менее, все готовые к использованию файлы можно найти в нашем Репозиторий GitHub .
2. Self Подпись Корень CA
Чтобы иметь возможность подписать наши серверные и клиентские сертификаты, мы должны сначала создать собственный сертификат root CA с самостоятельной подписью. Сюда Мы будем выступать в качестве нашего собственного сертификата .
Для этого мы будем использовать открывает библиотеки, поэтому мы должны установить его до следующего шага.
Давайте создадим сертификат CA:
openssl req -x509 -sha256 -days 3650 -newkey rsa:4096 -keyout rootCA.key -out rootCA.crt
Когда мы выполняем вышеупомяпную команду, мы должны предоставить пароль для нашего личного ключа. Для целей этого учебника мы используем changeit в качестве фразы.
Кроме того, мы должны ввести информацию, которая формирует так называемое выдающееся имя . Здесь мы предоставляем только CN (Общее название) – Baeldung.com – и оставить другие части пустыми.
3. Кейстор
Дополнительное требование : Для использования криптографически сильных ключей вместе с функциями шифрования и расшифровки нам понадобится « Java Cryptography Extension (JCE) Неограниченные файлы политики силы юрисдикции ” установлен в нашем JVM .
Они могут быть загружены, например, из Oracle (следуйте инструкциям по установке, включенным в загрузку). Некоторые дистрибутивы Linux также предоставляют устанавливаемый пакет через своих менеджеров пакетов.
Клавиатура является репозиторием, который наше приложение Spring Boot будет использовать для хвата частного ключа и сертификата нашего сервера. Другими словами, наше приложение будет использовать keystore для обслуживания сертификата для клиентов во время рукопожатия SSL.
В этом учебнике мы используем Формат Java Key-Store (JKS) и ключевые командно-линейный инструмент.
3.1. Сертификат на стороне сервера
Для реализации проверки подлинности X.509 на стороне сервера в нашем приложении Spring Boot мы сначала необходимо создать сертификат на стороне сервера.
Начнем с создания так называемого запроса на подписание сертификата (CSR):
openssl req -new -newkey rsa:4096 -keyout localhost.key –out localhost.csr
Аналогичным образом, что касается сертификата CA, мы должны предоставить пароль для частного ключа. Кроме того, давайте использовать localhost как общее название (CN).
Прежде чем приступить к работе, нам нужно создать файл конфигурации – localhost.ext . Он будет хранить некоторые дополнительные параметры, необходимые при подписании сертификата.
authorityKeyIdentifier=keyid,issuer basicConstraints=CA:FALSE subjectAltName = @alt_names [alt_names] DNS.1 = localhost
Готовый к использованию файл также доступен здесь .
Теперь пришло время подписать запрос с нашей rootCA.crt сертификат и его частная ключевая :
openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -in localhost.csr -out localhost.crt -days 365 -CAcreateserial -extfile localhost.ext
Обратите внимание, что мы должны предоставить тот же пароль, который мы использовали, когда мы создали наш сертификат CA.
На данном этапе мы, наконец, готовы использовать localhost.crt сертификат, подписанный нашим собственным сертификатом.
Для печати данных нашего сертификата в читаемой человеком форме мы можем использовать следующую команду:
openssl x509 -in localhost.crt -text
3.2. Импорт в Keystore
В этом разделе мы увидим, как импортировать подписанный сертификат и соответствующий частный ключ к keystore.jks файл .
Мы будем использовать Архив PKCS 12 , чтобы упаковать личный ключ нашего сервера вместе с подписанным сертификатом. Затем мы будем импортировать его в вновь созданный keystore.jks.
Мы можем использовать следующую команду для создания .p12 файл:
openssl pkcs12 -export -out localhost.p12 -name "localhost" -inkey localhost.key -in localhost.crt
Так что теперь у нас есть местный житель.key и localhost.crt в комплекте в одной localhost.p12 файл.
Давайте теперь использовать клавиатуру для создать keystore.jks репозиторий и импорт localhost.p12 файл с одним командным :
keytool -importkeystore -srckeystore localhost.p12 -srcstoretype PKCS12 -destkeystore keystore.jks -deststoretype JKS
На данном этапе у нас есть все для части проверки подлинности сервера. Давайте приступить к нашей конфигурации приложения Spring Boot.
4. Пример применения
Наш проект обеспеченного сервера SSL состоит из @SpringBootApplication аннотированный класс приложений (который является своего @Configuration ) , application.properts файл конфигурации и очень простой передний конец в стиле MVC.
Все, что приложение должно сделать, это представить HTML страницу с “Здравствуйте, пользователь!” Сообщение. Таким образом, мы можем проверить сертификат сервера в браузере, чтобы убедиться, что соединение проверено и защищено.
4.1. Зависимость от Maven
Во-первых, мы создаем новый проект Maven с тремя пакетами Spring Boot Starter:
org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-thymeleaf
Для справки: мы можем найти расслоения на Maven Central ( безопасности , веб- , и ).
4.2. Весенняя загрузка приложения
В качестве следующего шага мы создаем основной класс приложений и контроллер пользователя:
@SpringBootApplication public class X509AuthenticationServer { public static void main(String[] args) { SpringApplication.run(X509AuthenticationServer.class, args); } } @Controller public class UserController { @RequestMapping(value = "/user") public String user(Model model, Principal principal) { UserDetails currentUser = (UserDetails) ((Authentication) principal).getPrincipal(); model.addAttribute("username", currentUser.getUsername()); return "user"; } }
Теперь мы расскажем приложению, где найти нашу keystore.jks и как получить к нему доступ. Мы устанавливаем SSL на “включенный” статус и меняем стандартный порт прослушивания на указать защищенную связь.
Кроме того, мы настраиваем некоторые пользователь-детали для доступа к нашему серверу через базовую аутентификацию:
server.ssl.key-store=../store/keystore.jks server.ssl.key-store-password=${PASSWORD} server.ssl.key-alias=localhost server.ssl.key-password=${PASSWORD} server.ssl.enabled=true server.port=8443 spring.security.user.name=Admin spring.security.user.password=admin
Это будет HTML шаблон, расположенный в ресурсы/шаблоны папка:
X.509 Authentication Demo Hello !
4.3. Установка Root CA
Прежде чем мы закончим этот раздел и посмотреть на сайте, мы должны установить наш созданный корневой сертификат власти в качестве надежного сертификата в браузере .
Образцовая установка нашего сертификата для Mozilla Firefox будет выглядеть следующим образом:
- Тип о:предпочтения в адресной стойке
- Открытый Расширенный -> Сертификаты -> Просмотр сертификатов -> органы
- Нажмите на импорт
- Найдите Baeldung учебники папка и ее субфолдер весна-безопасность-x509/keystore
- Выберите rootCA.crt файл и нажмите Хорошо
- Выберите ” Доверьтесь этому CA для идентификации веб-сайтов” и нажмите Хорошо
Примечание: Если вы не хотите, чтобы добавить наши сертификат органа в список доверенные органы , Вы позже будете иметь возможность сделать исключение и показать веб-сайт жестким, даже если он упоминается как небезопасные. Но тогда вы увидите символ “желтый восклицательный знак” в адресной полосе, указывая на небезопасное соединение!
После этого мы перейдите на весна-безопасность-x509-основной аут модуль и запустить:
mvn spring-boot:run
Наконец, мы попали https://localhost:8443/user , введите наши учетные данные пользователей из application.properts и должны увидеть “Здравствуйте, администратор!” Сообщение. Теперь мы можем проверить состояние соединения, нажав на символ “зеленый замок” в адресной стойке, и это должно быть надежное соединение.
5. Взаимная аутентификация
В предыдущем разделе мы представили, как реализовать наиболее распространенную схему проверки подлинности SSL – проверку подлинности на стороне сервера. Это означает, что только сервер аутентичен для клиентов.
В этом разделе Мы опишем, как добавить другую часть проверки подлинности – проверку подлинности на стороне . Таким образом, только клиенты с действительными сертификатами, подписанными органом, который доверяет нашему серверу, могут получить доступ к нашему безопасному веб-сайту.
Но прежде чем мы продолжим, давайте посмотрим, каковы плюсы и минусы использования взаимной проверки подлинности SSL.
Плюсы:
- Частный ключ X.509 сертификат клиента сильнее, чем любой пользовательский пароль . Но это должно храниться в тайне!
- С сертификатом, личность клиента хорошо известна и легко проверить .
- Больше никаких забытых паролей!
Минусы:
- Мы должны создать сертификат для каждого нового клиента.
- Сертификат клиента должен быть установлен в клиентском приложении. На самом деле: Проверка подлинности клиента X.509 зависит от , что делает невозможным использование такого рода аутентификации в общественных местах, например, в интернет-кафе.
- Должен быть механизм отзыва скомпрометированных клиентских сертификатов.
- Мы должны поддерживать сертификаты клиентов. Это может легко стать дорогостоящим.
5.1. Трастстор
Доверие в некотором роде является противоположностью keystore. Он содержит сертификаты внешних организаций, которые мы .
В нашем случае достаточно сохранить корневой сертификат CA в доверительном магазине.
Давайте посмотрим, как создать truststore.jks файл и импортировать rootCA.crt с помощью клавиатуры:
keytool -import -trustcacerts -noprompt -alias ca -ext san=dns:localhost,ip:127.0.0.1 -file rootCA.crt -keystore truststore.jks
Обратите внимание, что мы должны предоставить пароль для вновь созданных trusstore.jks . Здесь мы снова использовали changeit фразы.
Вот и все, мы импортировали наш собственный сертификат CA, и truststore готов к использованию.
5.2. Весенняя конфигурация безопасности
Чтобы продолжить, мы изменяем нашу X509АентицияСервер для расширения от WebSecurityКонфигурерАдаптер и переопределить один из предоставленных методов настройки. Здесь мы настраиваем механизм x.509 для разбора Общее название (CN) поле сертификата для извлечения имен пользователей.
С помощью этих извлеченных имен пользователей Spring Security ищет в предоставленном ПользовательDetailsService для соответствующих пользователей. Таким образом, мы также реализуем этот интерфейс службы, содержащий одного демо-пользователя.
Совет: В производственных средах этот ПользовательDetailsService может загружать своих пользователей, например, с JDBC ДанныеИсточник .
Вы должны заметить, что мы аннотировать наш класс с @EnableWebSecurity и @EnableGlobalMethodSecurity с включенным предварительной/пост-авторизацией.
С последним мы можем аннотировать наши ресурсы с @PreAuthorize и @PostAuthorize для мелкозернистого контроля доступа:
@SpringBootApplication @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class X509AuthenticationServer extends WebSecurityConfigurerAdapter { ... @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().anyRequest().authenticated() .and() .x509() .subjectPrincipalRegex("CN=(.*?)(?:,|$)") .userDetailsService(userDetailsService()); } @Bean public UserDetailsService userDetailsService() { return new UserDetailsService() { @Override public UserDetails loadUserByUsername(String username) { if (username.equals("Bob")) { return new User(username, "", AuthorityUtils .commaSeparatedStringToAuthorityList("ROLE_USER")); } throw new UsernameNotFoundException("User not found!"); } }; } }
Как уже говорилось ранее, теперь мы можем использовать Управление доступом на основе выражения в нашем контроллере. В частности, наши аннотации к разрешению соблюдаются из-за @EnableGlobalMethodSecurity аннотация в нашем @Configuration :
@Controller public class UserController { @PreAuthorize("hasAuthority('ROLE_USER')") @RequestMapping(value = "/user") public String user(Model model, Principal principal) { ... } }
Обзор всех возможных вариантов авторизации можно найти в официальная документация .
В качестве последнего шага модификации, мы должны сказать приложению, где доверие магазин находится и что Проверка подлинности клиента SSL необходимо ( server.ssl.client-auth’need ).
Таким образом, мы ставим следующие в нашем application.properts :
server.ssl.trust-store=store/truststore.jks server.ssl.trust-store-password=${PASSWORD} server.ssl.client-auth=need
Теперь, если мы за запустите приложение и указать наш браузер, чтобы https://localhost:8443/user , мы становимся информированными, что сверстник не может быть проверен, и он отрицает, чтобы открыть наш сайт.
5.3. Сертификат на стороне клиента
Теперь пришло время создать сертификат на стороне клиента. Шаги, которые мы должны предпринять, в значительной степени такие же, как для сервера стороне сертификата мы уже создали.
Во-первых, мы должны создать запрос на подписание сертификата:
openssl req -new -newkey rsa:4096 -nodes -keyout clientBob.key -out clientBob.csr
Мы должны предоставить информацию, которая будет включена в сертификат. Для этого упражнения, Давайте ввести только общее имя (CN) – Боб . Это важно, так как мы используем эту запись во время авторизации, и только Боб распознается нашим примером приложения.
Далее, мы должны подписать запрос с нашим CA:
openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -in clientBob.csr -out clientBob.crt -days 365 -CAcreateserial
Последним шагом, который мы должны сделать, является пакет подписанного сертификата и частного ключа в файл PKCS:
openssl pkcs12 -export -out clientBob.p12 -name "clientBob" -inkey clientBob.key -in clientBob.crt
Наконец, мы готовы установить клиентский сертификат в браузере .
Опять же, мы будем использовать Firefox:
- Тип о:предпочтения в адресной стойке
- Открытый Расширенный -> Просмотр сертификатов -> Сертификаты
- Нажмите на импорт
- Найдите Baeldung учебники папка и ее субфолдер весна-безопасность-x509/store
- Выберите clientBob.p12 файл и нажмите Хорошо
- Ввените пароль для сертификата и нажмите Хорошо
Теперь, когда мы обновим наш веб-сайт, нам будет предложено выбрать клиентский сертификат, который мы хотели бы использовать:
Если мы видим долгожданное сообщение, как “Здравствуйте, Боб!” , Это означает, что все работает, как ожидалось!
6. Взаимная аутентификация с XML
Добавление проверки подлинности клиента X.509 в конфигурацию безопасности http в XML также возможно:
... ...
Чтобы настроить основной Tomcat, мы должны поставить наши keystore и наши доверие магазин в свою conf папку и редактировать сервер.xml :
Совет: С clientAuth установлен на “хочу” , SSL по-прежнему включен, даже если клиент не предоставляет действительный сертификат. Но в этом случае мы должны использовать второй механизм аутентификации, например, форму входа, для доступа к защищенным ресурсам.
7. Заключение
Таким образом, мы узнали как создать самостоятельно подписанный сертификат CA и как использовать его для подписания других сертификатов .
Кроме того, мы создали как серверные, так и клиентские сертификаты. Затем мы представили, как импортировать их в keystore и truststore соответственно.
Кроме того, теперь вы должны быть в состоянии пакет сертификата вместе с его частным ключом в формате PKCS12 .
Мы также обсудили, когда имеет смысл использовать проверку подлинности клиента Spring Security X.509, поэтому решение о том, внедрять его в веб-приложение или нет, принимается.
И, чтобы завершить, найти исходный код этой статьи на Github .