Рубрики
Без рубрики

Простой единый вход с Spring Security OAuth2 (legacy stack)

Простая реализация SSO с использованием Spring Security OAuth2 и Boot.

Автор оригинала: baeldung.

1. Обзор

В этом уроке мы обсудим, как реализовать SSO – Single Sign On – с помощью Spring Security OAuth и Spring Boot.

Мы будем использовать три отдельных приложения:

  • Сервер авторизации – это центральный механизм аутентификации
  • Два клиентских приложения: приложения, использующие SSO

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

И мы собираемся использовать тип Authorization Code grant из OAuth2 для управления делегированием аутентификации.

Примечание : в этой статье используется Spring OAuth legacy project . Для версии этой статьи, использующей новый стек Spring Security 5, ознакомьтесь с нашей статьей Simple Single Sign-On with Spring Security OAuth2 .

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 – без него все пути будут защищены – так что пользователи будут перенаправлены на вход, когда они попытаются получить доступ к любой странице. В нашем случае страницы индекса и входа в систему-это единственные страницы, к которым можно получить доступ без аутентификации.

Наконец, мы также определили компонент RequestContextListener bean для обработки областей запросов.

И 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 авторизации, на который будут перенаправлены пользователи
  • userInfo Uri URI конечной точки пользователя для получения текущих сведений о пользователе

Также обратите внимание, что в нашем примере мы развернули наш сервер авторизации, но, конечно, мы также можем использовать других сторонних поставщиков, таких как Facebook или GitHub.

2.3. Передний конец

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

Наше клиентское приложение здесь имеет очень простой интерфейс; вот 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 grant.

Кроме того, обратите внимание, что auto Approve имеет значение 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.

Как всегда, полный исходный код можно найти на GitHub .