«Я люблю писать код аутентификации и авторизации». Нет Java-разработчика. Надоело строить одни и те же экраны входа снова и снова? Попробуйте API Okta для размещенной аутентификации, авторизации и многофакторной аутентификации.
При создании веб-приложения авторизация и авторизация являются обязательными. Однако сделать это правильно не просто. Компьютерная безопасность — это настоящая специальность. Легионы разработчиков работают днем и ночью против одинаково многочисленных международных хакеров, создавая непрерывный цикл разработки для поиска уязвимостей, их атаки и исправления. Следить за всем этим соло было бы больно (если не невозможно).
К счастью, в этом нет необходимости. Spring Security и Spring Boot сделали реализацию веб-приложения с использованием OAuth 2.0 приятной и простой. Кроме того, Okta, поставщик доступа к программному обеспечению как удостоверению личности, использует Spring Boot, чтобы сделать процесс еще проще.
В этом руководстве вы сначала создадите веб-приложение OAuth 2.0 и сервер аутентификации, используя Spring Boot и Spring Security. После этого вы будете использовать Okta, чтобы избавиться от собственного сервера аутентификации и еще больше упростить приложение Spring Boot.
Давайте начнем!
Создайте сервер OAuth 2.0
Начните с перехода к Spring Initializr и создания нового проекта со следующими настройками:
- Измените тип проекта с Maven на Gradle .
- Измените группу на com.okta.spring .
- Измените артефакт на AuthorizationServerApplication .
- Добавьте одну зависимость: Web .
Скачайте проект и скопируйте его куда-нибудь на свой жесткий диск. В этом уроке вы создадите три разных проекта, так что вы можете захотеть создать родительский каталог, где-то вроде SpringBootOAuth
.
Вам нужно добавить одну зависимость в файл build.gradle
:
implementation 'org.springframework.security.oauth:spring-security-oauth2:2.3.3.RELEASE' |
Это добавляет OAuth совершенства Spring.
Обновите src/main/resources/application.properties
чтобы он соответствовал:
server.port=8081 server.servlet.context-path= /auth user.oauth.clientId=R2dpxQ3vPrtfgF72 user.oauth.clientSecret=fDw7Mpkk5czHNuSRtmhGmAGL42CaxQB9 user.oauth.redirectUris=http: //localhost :8082 /login/oauth2/code/ user.oauth.user.username=Andrew user.oauth.user.password=abcd |
Это устанавливает порт сервера, путь контекста сервлета и некоторые значения по умолчанию для оперативной памяти, сгенерированных ad-hoc токенов, которые сервер собирается вернуть клиенту, а также для имени пользователя и пароля нашего пользователя. В производственной среде вам потребуется немного более сложный сервер для реального сервера аутентификации без жестко закодированных URI перенаправления, а также имен пользователей и паролей.
Обновите класс AuthorizationServerApplication
добавив @EnableResourceServer
:
package com.okta.spring.AuthorizationServerApplication; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; @SpringBootApplication @EnableResourceServer public class AuthorizationServerApplication { public static void main(String[] args) { SpringApplication.run(AuthorizationServerApplication. class , args); } } |
Создайте новый класс AuthServerConfig
в том же пакете, что и ваш класс приложения com.okta.spring.AuthorizationServerApplication
в src/main/java
(отныне создавайте Java-классы в src/main/java/com/okta/spring/AuthorizationServerApplication
). Этот класс конфигурации Spring включает и настраивает сервер авторизации OAuth.
package com.okta.spring.AuthorizationServerApplication; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; @Configuration @EnableAuthorizationServer public class AuthServerConfig extends AuthorizationServerConfigurerAdapter { @Value ( "${user.oauth.clientId}" ) private String ClientID; @Value ( "${user.oauth.clientSecret}" ) private String ClientSecret; @Value ( "${user.oauth.redirectUris}" ) private String RedirectURLs; private final PasswordEncoder passwordEncoder; public AuthServerConfig(PasswordEncoder passwordEncoder) { this .passwordEncoder = passwordEncoder; } @Override public void configure( AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.tokenKeyAccess( "permitAll()" ) .checkTokenAccess( "isAuthenticated()" ); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient(ClientID) .secret(passwordEncoder.encode(ClientSecret)) .authorizedGrantTypes( "authorization_code" ) .scopes( "user_info" ) .autoApprove( true ) .redirectUris(RedirectURLs); } } |
Класс AuthServerConfig
— это класс, который создает и возвращает наши веб-токены JSON при правильной аутентификации клиента.
Создайте класс SecurityConfiguration
:
package com.okta.spring.AuthorizationServerApplication; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @Configuration @Order ( 1 ) public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Value ( "${user.oauth.user.username}" ) private String username; @Value ( "${user.oauth.user.password}" ) private String password; @Override protected void configure(HttpSecurity http) throws Exception { http.requestMatchers() .antMatchers( "/login" , "/oauth/authorize" ) .and() .authorizeRequests() .anyRequest().authenticated() .and() .formLogin().permitAll(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser(username) .password(passwordEncoder().encode(password)) .roles( "USER" ); } @Bean public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } } |
Класс SecurityConfiguration
— это класс, который фактически проверяет подлинность запросов к вашему серверу авторизации. Обратите внимание на верхнюю часть, где он извлекает имя пользователя и пароль из файла application.properties
.
Наконец, создайте класс Java с именем UserController
:
package com.okta.spring.AuthorizationServerApplication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.security.Principal; @RestController public class UserController { @GetMapping ( "/user/me" ) public Principal user(Principal principal) { return principal; } } |
Этот файл позволяет клиентским приложениям узнать больше о пользователях, которые проходят аутентификацию на сервере.
Это ваш ресурсный сервер! Не так уж плохо. Spring Boot делает это довольно легко. Четыре файла и несколько свойств. Чуть позже вы сделаете это еще проще с Okta, но сейчас перейдем к созданию клиентского приложения, которое вы можете использовать для тестирования сервера аутентификации.
Запустите сервер авторизации:
. /gradlew bootRun |
Подождите немного, пока он закончит работу. Терминал должен заканчиваться примерно так:
... 2019-02-23 19:06:49.122 INFO 54333 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8081 (http) with context path '/auth ' 2019-02-23 19:06:49.128 INFO 54333 --- [ main] c.o.s.A.AuthorizationServerApplication : Started AuthorizationServerApplication in 3.502 seconds (JVM running for 3.945) |
ПРИМЕЧАНИЕ. Если вы получаете сообщение об ошибке JAXB ( java.lang.ClassNotFoundException: javax.xml.bind.JAXBException
), то это потому, что вы используете Java 11. Чтобы это исправить, добавьте JAXB в свой build.gradle
.
implementation 'org.glassfish.jaxb:jaxb-runtime' |
Создайте свое клиентское приложение
Вернуться к Весне Инициализр . Создайте новый проект со следующими настройками:
- Тип проекта должен быть Gradle (не Maven).
- Группа: com.okta.spring .
- Артефакт: SpringBootOAuthClient .
- Добавьте три зависимости: Web , Thymeleaf , OAuth2 Client .
Загрузите проект, скопируйте его в место последнего распаковывания и распакуйте его.
На этот раз вам нужно добавить следующую зависимость в ваш файл build.gradle
:
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.0.4.RELEASE' |
Переименуйте src/main/resources/application.properties
в application.yml
и обновите его, чтобы он соответствовал YAML ниже:
server: port: 8082 session: cookie: name: UISESSION spring: thymeleaf: cache: false security: oauth2: client: registration: custom-client: client- id : R2dpxQ3vPrtfgF72 client-secret: fDw7Mpkk5czHNuSRtmhGmAGL42CaxQB9 client-name: Auth Server scope: user_info provider: custom-provider redirect-uri-template: http: //localhost :8082 /login/oauth2/code/ client-authentication-method: basic authorization-grant- type : authorization_code provider: custom-provider: token-uri: http: //localhost :8081 /auth/oauth/token authorization-uri: http: //localhost :8081 /auth/oauth/authorize user-info-uri: http: //localhost :8081 /auth/user/me user-name-attribute: name |
Обратите внимание, что здесь вы настраиваете clientId
и clientSecret
, а также различные URI для вашего сервера аутентификации. Они должны соответствовать значениям в другом проекте.
Обновите класс SpringBootOAuthClientApplication
чтобы он соответствовал:
package com.okta.spring.SpringBootOAuthClient; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringBootOAuthClientApplication { public static void main(String[] args) { SpringApplication.run(SpringBootOAuthClientApplication. class , args); } } |
Создайте новый класс Java с именем WebController
:
package com.okta.spring.SpringBootOAuthClient; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import java.security.Principal; @Controller public class WebController { @RequestMapping ( "/securedPage" ) public String securedPage(Model model, Principal principal) { return "securedPage" ; } @RequestMapping ( "/" ) public String index(Model model, Principal principal) { return "index" ; } } |
Это контроллер, который отображает входящие запросы в ваши файлы шаблонов Thymeleaf (которые вы сделаете через секунду).
Создайте другой класс Java с именем SecurityConfiguration
:
package com.okta.spring.SpringBootOAuthClient; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.antMatcher( "/**" ).authorizeRequests() .antMatchers( "/" , "/login**" ).permitAll() .anyRequest().authenticated() .and() .oauth2Login(); } } |
Этот класс определяет конфигурацию Spring Security для вашего приложения: разрешает все запросы на домашнем пути и требует аутентификации для всех других маршрутов. он также устанавливает поток входа в Spring Boot OAuth.
Последние файлы, которые вам нужно добавить, — это два файла шаблона Thymeleaf. Полное рассмотрение шаблонов Thymeleaf выходит далеко за рамки данного руководства, но вы можете взглянуть на их веб-сайт для получения дополнительной информации.
Шаблоны находятся в каталоге src/main/resources/templates
. Вы заметите в контроллере выше, что они просто возвращают строки для маршрутов. Когда в сборку включены зависимости Thymeleaf, Spring Boot автоматически предполагает, что вы возвращаете имя файла шаблона из контроллеров, и поэтому приложение будет искать в src/main/resources/templates
имя файла с возвращенной строкой плюс .html
.
Создайте домашний шаблон: src/main/resources/templates/index.html
:
<! DOCTYPE html> < html lang = "en" > < head > < meta charset = "UTF-8" > < title >Home</ title > </ head > < body > < h1 >Spring Security SSO</ h1 > < a href = "securedPage" >Login</ a > </ body > </ html > |
И защищенный шаблон: src/main/resources/templates/securedPage.html
:
<! DOCTYPE html> < head > < meta charset = "UTF-8" > < title >Secured Page</ title > </ head > < body > < h1 >Secured Page</ h1 > < span th:text = "${#authentication.name}" ></ span > </ body > </ html > |
Я просто укажу на одну строку:
< span th:text = "${#authentication.name}" ></ span > |
Это строка, которая будет вставлять имя аутентифицированного пользователя. В этой строке вам понадобилась org.thymeleaf.extras:thymeleaf-extras-springsecurity5
в файле build.gradle
.
Запустите клиентское приложение:
. /gradlew bootRun |
Подожди, пока оно закончится. Терминал должен заканчиваться примерно так:
... 2019-02-23 19:29:04.448 INFO 54893 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8082 (http) with context path '' 2019-02-23 19:29:04.453 INFO 54893 --- [ main] c.o.s.S.SpringBootOAuthClientApplication : Started SpringBootOAuthClientApplication in 3.911 seconds (JVM running for 4.403) |
Протестируйте сервер ресурсов
Перейдите в выбранном браузере к клиентскому приложению по адресу http://localhost:8082/
.
Нажмите на ссылку Войти .
Вы будете перенаправлены на страницу входа:
Введите имя пользователя Andrew и пароль abcd (из файла application.properties
с сервера аутентификации).
Нажмите « Войти», и вы попадете в супер-необычный шаблон securedPage.html с надписью «Защищенная страница» и «Эндрю».
Большой! Оно работает. Теперь ты собираешься сделать это еще проще.
Вы можете остановить как серверные, так и клиентские приложения Spring Boot.
Создать приложение OpenID Connect
Okta является провайдером аутентификации и авторизации SaaS (программное обеспечение как услуга). Мы предоставляем бесплатные аккаунты разработчикам, чтобы они могли без проблем создавать приложения OIDC. Зайдите на сайт developer.okta.com и зарегистрируйтесь. После того как вы подтвердили свою электронную почту, войдите в систему и выполните следующие действия:
- Перейдите в Приложение > Добавить приложение .
- Выберите тип приложения Web и нажмите Next .
- Дайте приложению имя. Я назвал мой «Spring Boot OAuth».
- В разделе URI перенаправления входа в систему измените значение на
http://localhost:8080/login/oauth2/code/okta
. Остальные значения по умолчанию будут работать. - Нажмите Готово .
Оставьте страницу открытой, чтобы принять к сведению идентификатор клиента и секрет клиента . Они понадобятся тебе через минуту.
Создать новое приложение Spring Boot
Вернемся к Spring Initializr еще раз. Создайте новый проект со следующими настройками:
- Измените тип проекта с Maven на Gradle .
- Измените группу на com.okta.spring .
- Измените Артефакт на OktaOAuthClient .
- Добавьте три зависимости: Web , Thymeleaf , Okta .
- Нажмите Создать проект .
Скопируйте проект и распакуйте его куда-нибудь.
В файле build.gradle
добавьте следующую зависимость:
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.0.4.RELEASE' |
Также, пока вы там, обратите внимание на зависимость com.okta.spring:okta-spring-boot-starter:1.1.0
. Это Okta Spring Boot Starter. Это удобный проект, который делает интеграцию Okta с Spring Boot приятной и простой. Для получения дополнительной информации взгляните на GitHub проекта .
Измените src/main/resources/application.properties
на application.yml
и добавьте следующее:
server: port: 8080 okta: oauth2: issuer: https: // {yourOktaDomain} /oauth2/default client- id : {yourClientId} client-secret: {yourClientSecret} spring: thymeleaf: cache: false |
Помните, когда я сказал, что вам понадобится ваш ClientID и Client Secret выше. Ну, время пришло. Вы должны заполнить их в файл, а также ваш URL издателя Okta. Это будет выглядеть примерно так: dev-123456.okta.com
. Вы можете найти его в разделе API > Серверы авторизации .
Вам также понадобятся два похожих файла шаблона в каталоге src/main/resources/templates
. Файл шаблона index.html
точно такой же, и его можно скопировать, если хотите. securedPage.html
шаблона securedPage.html
немного отличается из-за способа, которым информация об аутентификации возвращается из Okta по сравнению с простым сервером аутентификации, который вы создали ранее.
Создайте домашний шаблон: src/main/resources/templates/index.html
:
<! DOCTYPE html> < html lang = "en" > < head > < meta charset = "UTF-8" > < title >Home</ title > </ head > < body > < h1 >Spring Security SSO</ h1 > < a href = "securedPage" >Login</ a > </ body > </ html > |
И защищенный шаблон: src/main/resources/templates/securedPage.html
:
<! DOCTYPE html> < head > < meta charset = "UTF-8" > < title >Secured Page</ title > </ head > < body > < h1 >Secured Page</ h1 > < span th:text = "${#authentication.principal.attributes.name}" >Joe Coder</ span > </ body > </ html > |
Создайте класс Java с именем WebController
в пакете com.okta.spring.SpringBootOAuth
:
package com.okta.spring.OktaOAuthClient; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import java.security.Principal; @Controller public class WebController { @RequestMapping ( "/securedPage" ) public String securedPage(Model model, Principal principal) { return "securedPage" ; } @RequestMapping ( "/" ) public String index(Model model, Principal principal) { return "index" ; } } |
Этот класс просто создает два маршрута, один для домашнего маршрута и один для защищенного маршрута. Опять же, Spring Boot и Thymeleaf автоматически маскируют это для двух файлов шаблонов в src/main/resources/templates
.
Наконец, создайте еще один Java-класс имен SecurityConfiguration
:
package com.okta.spring.OktaOAuthClient; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.antMatcher( "/**" ).authorizeRequests() .antMatchers( "/" ).permitAll() .anyRequest().authenticated() .and() .oauth2Login(); } } |
Это оно! Бам!
Запустите клиент с поддержкой Okta-OAuth:
. /gradlew bootRun |
Вы должны увидеть кучу выходных данных, которые заканчиваются на:
... 2019-02-23 20:09:03.465 INFO 55890 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2019-02-23 20:09:03.470 INFO 55890 --- [ main] c.o.s.O.OktaOAuthClientApplication : Started OktaOAuthClientApplication in 3.285 seconds (JVM running for 3.744) |
Перейдите по адресу http: // localhost: 8080 .
Нажмите кнопку Войти .
На этот раз вы будете перенаправлены на страницу входа в Okta. Вам может понадобиться использовать браузер в режиме инкогнито или выйти из своей панели мониторинга developer.okta.com, чтобы не пропустить страницу входа и не получить немедленный доступ к защищенной конечной точке.
Авторизуйтесь, и вы увидите защищенную страницу с вашим именем!
Узнайте больше о Spring Boot, Spring Security и OAuth 2.0
Вот и все. Супер просто. В предыдущем руководстве вы рассмотрели, как использовать Spring Boot и Spring Security для реализации базового сервера аутентификации и клиентского приложения. Затем вы использовали Okta, чтобы сделать еще более простое клиентское приложение с полнофункциональной аутентификацией SSO и OAuth.
Вы можете увидеть готовый код этого руководства на GitHub по адресу oktadeveloper / okta-spring-boot-authz-server-example .
Если вы хотите узнать больше о Spring Boot, OAuth 2.0 и Spring Security, ознакомьтесь с этими полезными руководствами:
- Начните с Spring Boot, OAuth 2.0 и Okta
- Что, черт возьми, OAuth?
- Начните с Spring Security 5.0 и OIDC
- Идентификационные данные, утверждения и токены — учебник по OpenID Connect, часть 1 из 3
- Создайте безопасный API с помощью Spring Boot и GraphQL
Если у вас есть какие-либо вопросы по поводу этого поста, пожалуйста, добавьте комментарий ниже. Чтобы получить более интересный контент, следите за @oktadev в Twitter или подпишитесь на наш канал на YouTube !
«Краткое руководство по OAuth 2.0 с Spring Security» первоначально было опубликовано в блоге разработчиков Okta в марте 2019 года.
«Я люблю писать код аутентификации и авторизации». Нет Java-разработчика. Надоело строить одни и те же экраны входа снова и снова? Попробуйте API Okta для размещенной аутентификации, авторизации и многофакторной аутентификации.