Простой единый вход в Spring Security OAuth2
1. обзор
В этом руководстве мы обсудим, как реализовать SSO - Single Sign On - с помощью Spring Security OAuth и Spring Boot.
Мы будем использовать три отдельных приложения:
-
Сервер авторизации - это центральный механизм аутентификации
-
Два клиентских приложения: приложения, использующие единый вход
Проще говоря, когда пользователь пытается получить доступ к защищенной странице в клиентском приложении, он сначала будет перенаправлен на аутентификацию через сервер аутентификации.
И мы собираемся использовать тип предоставленияAuthorization Code из OAuth2, чтобы управлять делегированием аутентификации.
Дальнейшее чтение:
Spring Security 5 - OAuth2 Войти
Узнайте, как аутентифицировать пользователей с помощью Facebook, Google или других учетных данных с помощью OAuth2 в Spring Security 5.
Новое в Spring Security OAuth2 - Проверка заявок
Краткое практическое введение в новую поддержку проверки претензий в Spring Security OAuth.
Вторичный вход в Facebook через Spring Social
Краткий обзор реализации аутентификации на основе Facebook рядом со стандартным приложением Spring для входа в форму.
Прежде чем мы начнем - одно важное замечание. Имейте в виду, чтоthe Spring Security core team is in the process of implementing a new OAuth2 stack - некоторые аспекты уже выполнены, а некоторые все еще находятся в процессе разработки.
Вот короткое видео, которое даст вам некоторый контекст вокруг этих усилий:
Хорошо, приступим.
2. Клиентское приложение
Начнем с нашего клиентского приложения; мы, конечно, будем использовать Spring Boot, чтобы минимизировать конфигурацию:
2.1. Maven Зависимости
Во-первых, нам потребуются следующие зависимости в нашемpom.xml:
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-security
org.springframework.security.oauth.boot
spring-security-oauth2-autoconfigure
2.0.1.RELEASE
org.springframework.boot
spring-boot-starter-thymeleaf
org.thymeleaf.extras
thymeleaf-extras-springsecurity4
2.2. Конфигурация безопасности
Далее, самая важная часть, настройка безопасности нашего клиентского приложения:
@Configuration
@EnableOAuth2Sso
public class UiSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/login**")
.permitAll()
.anyRequest()
.authenticated();
}
}
Ядром этой конфигурации, конечно же, является аннотация@EnableOAuth2Sso, которую мы используем для включения единого входа.
Обратите внимание, что нам нужно расширитьWebSecurityConfigurerAdapter - без него все пути будут защищены - поэтому пользователи будут перенаправлены для входа в систему, когда они попытаются получить доступ к любой странице. В нашем случае страницы индекса и логина являются единственными страницами, к которым можно получить доступ без аутентификации.
Наконец, мы также определили bean-компонентRequestContextListener для обработки областей запросов.
Иapplication.yml:
server:
port: 8082
servlet:
context-path: /ui
session:
cookie:
name: UISESSION
security:
basic:
enabled: false
oauth2:
client:
clientId: SampleClientId
clientSecret: secret
accessTokenUri: http://localhost:8081/auth/oauth/token
userAuthorizationUri: http://localhost:8081/auth/oauth/authorize
resource:
userInfoUri: http://localhost:8081/auth/user/me
spring:
thymeleaf:
cache: false
Несколько быстрых заметок:
-
мы отключили стандартную базовую аутентификацию
-
accessTokenUri - это URI для получения токенов доступа
-
userAuthorizationUri - это URI авторизации, на который будут перенаправлены пользователи.
-
userInfoUri URI конечной точки пользователя для получения сведений о текущем пользователе
Также обратите внимание, что в нашем примере мы развернули наш Сервер авторизации, но, конечно, мы также можем использовать других сторонних поставщиков, таких как Facebook или GitHub.
2.3. Внешний интерфейс
Теперь давайте посмотрим на конфигурацию внешнего интерфейса нашего клиентского приложения. Мы не собираемся здесь заострять внимание на этом, в основном потому, что мыalready covered in on the site.
У нашего клиентского приложения очень простой интерфейс; вотindex.html:
Spring Security SSO
Login
ИsecuredPage.html:
Secured Page
Welcome, Name
СтраницаsecuredPage.html требовала аутентификации пользователей. Если неаутентифицированный пользователь попытается получить доступ кsecuredPage.html, он сначала будет перенаправлен на страницу входа.
3. Сервер аутентификации
Теперь давайте обсудим здесь наш сервер авторизации.
3.1. Maven Зависимости
Во-первых, нам нужно определить зависимости в нашемpom.xml:
org.springframework.boot
spring-boot-starter-web
org.springframework.security.oauth
spring-security-oauth2
2.3.3.RELEASE
3.2. Конфигурация OAuth
Важно понимать, что здесь мы собираемся запустить сервер авторизации и сервер ресурсов вместе, как единое развертываемое устройство.
Начнем с настройки нашего сервера ресурсов, который выполняет функции основного загрузочного приложения:
@SpringBootApplication
@EnableResourceServer
public class AuthorizationServerApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(AuthorizationServerApplication.class, args);
}
}
Затем мы настроим наш сервер авторизации:
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private BCryptPasswordEncoder 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("SampleClientId")
.secret(passwordEncoder.encode("secret"))
.authorizedGrantTypes("authorization_code")
.scopes("user_info")
.autoApprove(true)
.redirectUris(
"http://localhost:8082/ui/login","http://localhost:8083/ui2/login");
}
}
Обратите внимание, что мы включаем только простой клиент, использующий тип предоставленияauthorization_code.
Также обратите внимание, что дляautoApprove задано значение true, чтобы нас не перенаправляли и не повышали для утверждения каких-либо областей вручную.
3.3. Конфигурация безопасности
Во-первых, мы отключим базовую аутентификацию по умолчанию с помощью нашегоapplication.properties:
server.port=8081
server.servlet.context-path=/auth
Теперь давайте перейдем к настройке и определим простой механизм входа в систему:
@Configuration
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@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("john")
.password(passwordEncoder().encode("123"))
.roles("USER");
}
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
Обратите внимание, что мы использовали простую аутентификацию в памяти, но мы можем просто заменить ее на собственныйuserDetailsService.
3.4. Конечная точка пользователя
Наконец, мы создадим нашу пользовательскую конечную точку, которую мы использовали ранее в нашей конфигурации:
@RestController
public class UserController {
@GetMapping("/user/me")
public Principal user(Principal principal) {
return principal;
}
}
Естественно, это вернет пользовательские данные в JSON-представлении.
4. Заключение
В этом кратком руководстве мы сосредоточились на реализации единого входа с использованием Spring Security Oauth2 и Spring Boot.
Как всегда, полный исходный код можно найтиover on GitHub.