«1. Обзор

В Spring Security добавлена ​​поддержка OAuth для WebFlux, начиная с версии 5.1.x GA.

Мы обсудим, как настроить наше приложение WebFlux для использования поддержки входа OAuth2. Мы также обсудим, как использовать WebClient для доступа к защищенным ресурсам OAuth2.

Конфигурация входа OAuth для Webflux аналогична конфигурации для стандартного веб-приложения MVC. Подробнее об этом читайте в нашей статье об элементе Spring OAuth2Login.

2. Конфигурация Maven

Для начала мы создадим простое приложение Spring Boot и добавим следующие зависимости в наш pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-client</artifactId>
</dependency>

Spring-boot-starter-security, spring- Зависимости boot-starter-webflux и spring-security-oauth2-client доступны на Maven Central.

3. Главный контроллер

Далее мы добавим простой контроллер для отображения имени пользователя на домашней странице:

@RestController
public class MainController {
    
    @GetMapping("/")
    public Mono<String> index(@AuthenticationPrincipal Mono<OAuth2User> oauth2User) {
       return oauth2User
        .map(OAuth2User::getName)
        .map(name -> String.format("Hi, %s", name));
    }
}

Обратите внимание, что мы будем отображать имя пользователя, полученное из конечной точки UserInfo клиента OAuth2.

4. Вход с помощью Google

Теперь мы настроим наше приложение для поддержки входа с помощью Google.

Сначала нам нужно создать новый проект в консоли разработчика Google

Теперь нам нужно добавить учетные данные OAuth2 (Создать учетные данные \u003e Идентификатор клиента OAuth).

Затем мы добавим это в «URI авторизованного перенаправления»:

http://localhost:8080/login/oauth2/code/google

Затем нам нужно настроить наш application.yml для использования идентификатора клиента и секрета:

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: YOUR_APP_CLIENT_ID
            client-secret: YOUR_APP_CLIENT_SECRET

Поскольку мы иметь spring-security-oauth2-client на нашем пути, наше приложение будет защищено.

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

5. Вход с помощью Auth Provider

Мы также можем настроить наше приложение для входа с пользовательского сервера авторизации.

В следующем примере мы будем использовать наш сервер авторизации из предыдущей статьи.

На этот раз нам нужно настроить больше свойств, а не только ClientID и Client Secret:

spring:
  security:
    oauth2:
      client:
        registration:
          custom:
            client-id: fooClientIdPassword
            client-secret: secret
            scopes: read,foo
            authorization-grant-type: authorization_code
            redirect-uri-template: http://localhost:8080/login/oauth2/code/custom
        provider:
          custom:
            authorization-uri: http://localhost:8081/spring-security-oauth-server/oauth/authorize
            token-uri: http://localhost:8081/spring-security-oauth-server/oauth/token
            user-info-uri: http://localhost:8088/spring-security-oauth-resource/users/extra
            user-name-attribute: user_name

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

Наконец, нам нужно настроить конечную точку UserInfo, чтобы иметь возможность получать данные аутентификации пользователя.

6. Конфигурация безопасности

По умолчанию Spring Security защищает все пути. Поэтому, если у нас есть только один клиент OAuth, мы будем перенаправлены для авторизации этого клиента и входа в систему.

Если зарегистрировано несколько клиентов OAuth, то будет автоматически создана страница входа для выбора метода входа.

Мы можем изменить это, если хотим, и предоставить подробную конфигурацию безопасности:

@EnableWebFluxSecurity
public class SecurityConfig {

    @Bean
    public SecurityWebFilterChain configure(ServerHttpSecurity http) throws Exception {
        return http.authorizeExchange()
          .pathMatchers("/about").permitAll()
          .anyExchange().authenticated()
          .and().oauth2Login()
          .and().build();
    }
}

В этом примере мы защитили все пути, кроме «/about».

7. WebClient

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

Теперь давайте настроим наш WebClient:

@Bean
public WebClient webClient(ReactiveClientRegistrationRepository clientRegistrationRepo, 
  ServerOAuth2AuthorizedClientRepository authorizedClientRepo) {
    ServerOAuth2AuthorizedClientExchangeFilterFunction filter = 
      new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrationRepo, authorizedClientRepo);
    
    return WebClient.builder().filter(filter).build();
}

Затем мы можем получить защищенный ресурс OAuth2:

@Autowired
private WebClient webClient;

@GetMapping("/foos/{id}")
public Mono<Foo> getFooResource(@RegisteredOAuth2AuthorizedClient("custom") 
  OAuth2AuthorizedClient client, @PathVariable final long id){
    return webClient
      .get()
      .uri("http://localhost:8088/spring-security-oauth-resource/foos/{id}", id)
      .attributes(oauth2AuthorizedClient(client))
      .retrieve()
      .bodyToMono(Foo.class); 
}

Обратите внимание, что мы получили удаленный ресурс Foo, используя AccessToken из OAuth2AuthorizedClient.

8. Заключение

В этой быстрой статье мы узнали, как настроить наше приложение WebFlux для использования поддержки входа OAuth2 и как использовать WebClient для доступа к защищенным ресурсам OAuth2.

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