«1. Обзор

В этом руководстве мы поговорим об аннотациях @EnableResourceServer и @EnableOAuth2Sso в Spring Security.

Мы начнем с объяснения различий между клиентом OAuth2 и сервером ресурсов OAuth2. После этого мы немного поговорим о том, что эти аннотации могут сделать для нас, и продемонстрируем их использование на примере с использованием Zuul и простого API.

В этой статье мы предполагаем, что у вас уже есть опыт работы с Zuul и OAuth2.

Если у вас их нет или вы считаете, что обзор любого из них был бы полезен, обратитесь к нашему краткому обзору Zuul и нашему руководству по OAuth2.

2. Клиент OAuth2 и сервер ресурсов

В OAuth2 есть четыре различных роли, которые нам необходимо рассмотреть:

    Владелец ресурса — объект, который может предоставить доступ к своим защищенным ресурсам Сервер авторизации — предоставляет токены доступа Клиентам после успешной аутентификации владельцев ресурсов и получения их авторизации. Сервер ресурсов — компонент, которому требуется токен доступа, чтобы разрешить или, по крайней мере, рассмотреть возможность доступа к своим ресурсам. токены с серверов авторизации

Аннотирование нашего класса конфигурации с помощью @EnableResourceServer или @EnableOAuth2Sso указывает Spring настроить компоненты, которые преобразуют наше приложение в одну из двух последних ролей, упомянутых выше.

Аннотация @EnableResourceServer позволяет нашему приложению вести себя как сервер ресурсов, настроив OAuth2AuthenticationProcessingFilter и другие не менее важные компоненты.

Ознакомьтесь с классом ResourceServerSecurityConfigurer, чтобы лучше понять, что настраивается за кулисами.

И наоборот, аннотация @EnableOAuth2Sso превращает наше приложение в клиент OAuth2. Он указывает Spring настроить OAuth2ClientAuthenticationProcessingFilter вместе с другими компонентами, которые необходимы нашему приложению для получения токенов доступа с сервера авторизации.

Взгляните на класс SsoSecurityConfigurer для получения дополнительной информации о том, что Spring настраивает для нас.

Объединение этих аннотаций с некоторыми свойствами позволяет нам быстро наладить работу. Давайте создадим два разных приложения, чтобы увидеть их в действии и то, как они могут дополнять друг друга:

    Нашим первым приложением будет пограничный узел, простое приложение Zuul, которое будет использовать аннотацию @EnableOAuth2Sso. Оно будет отвечать за аутентификацию пользователей (с помощью сервера авторизации) и делегирование входящих запросов другим приложениям. Второе приложение будет использовать аннотацию @EnableResourceServer и будет разрешать доступ к защищенным ресурсам, если входящие запросы содержат действительный доступ OAuth2. token

3. Zuul — @EnableOAuth2Sso

Давайте начнем с создания приложения Zuul, которое будет действовать как наш пограничный узел и будет отвечать за аутентификацию пользователей с использованием сервера авторизации OAuth2:

@Configuration
@EnableZuulProxy
@EnableOAuth2Sso
@Order(value = 0)
public class AppConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private ResourceServerTokenServices 
      resourceServerTokenServices;

    @Override
    public void configure(HttpSecurity http) throws Exception { 
        http.csrf().disable()
            .authorizeRequests()
            .antMatchers("/authorization-server-1/**",
              "/login").permitAll()
            .anyRequest().authenticated().and()
            .logout().permitAll().logoutSuccessUrl("/");
    }
}

~ ~~ Аннотирование нашего приложения Zuul с помощью @EnableOAuth2Sso также уведомляет Spring о настройке фильтра OAuth2TokenRelayFilter. Этот фильтр извлекает ранее полученные маркеры доступа из сеансов HTTP пользователей и распространяет их ниже по течению.

Обратите внимание, что мы также используем аннотацию @Order в нашем классе конфигурации AppConfiguration. Это делается для того, чтобы фильтры, созданные нашим адаптером WebSecurityConfigurerAdapter, имели приоритет над фильтрами, созданными другими адаптерами WebSecurityConfigurerAdapter.

Например, мы могли бы аннотировать наше приложение Zuul с помощью @EnableResourceServer для поддержки как идентификаторов сеанса HTTP, так и токенов доступа OAuth2. Однако при этом создаются новые фильтры, которые по умолчанию имеют приоритет над фильтрами, созданными классом AppConfiguration. Это происходит из-за того, что ResouceServerConfiguration, класс конфигурации, запускаемый @EnableResourceServer, указывает порядок по умолчанию 3, в то время как WebSecurityConfigureAdapter имеет порядок по умолчанию 100.

«Прежде чем мы перейдем к нашему серверу ресурсов, нам нужно настроить некоторые свойства:

zuul:
  routes:
    resource-server-mvc-1: /resource-server-mvc-1/**
    authorization-server-1:
      sensitiveHeaders: Authorization
      path: /authorization-server-1/**
      stripPrefix: false
  add-proxy-headers: true

security:
  basic:
    enabled: false
  oauth2:
    sso:
      loginPath: /login
    client:
      accessTokenUri: http://localhost:8769/authorization-server-1/oauth/token
      userAuthorizationUri: /authorization-server-1/oauth/authorize
      clientId: fooClient
      clientSecret: fooSecret
    resource:
      jwt:
        keyValue: "abc"
      id: fooScope
      serviceId: ${PREFIX:}resource

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

    Настраиваем наши маршруты Zuul и сообщаем, какие заголовки следует добавить/ удаляются перед отправкой запросов вниз по течению. Установка некоторых свойств OAuth2 для нашего приложения, чтобы иметь возможность взаимодействовать с нашим сервером авторизации и настройка JWT с симметричным шифрованием.

4. API — @EnableResourceServer

Теперь, когда у нас есть приложение Zuul, давайте создадим наш сервер ресурсов:

@SpringBootApplication
@EnableResourceServer
@Controller
@RequestMapping("/")
class ResourceServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ResourceServerApplication.class, args);
    }

    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public String helloWorld(Principal principal) {
        return "Hello " + principal.getName();
    }
}

Это простое приложение, которое предоставляет единственную конечную точку для возврата имени Принципал, инициировавший запрос.

Давайте завершим настройку некоторых свойств:

security:
  basic:
    enabled: false
  oauth2:
    resource:
      jwt:
        keyValue: "abc"
      id: fooScope
      service-id: ${PREFIX:}resource

Имейте в виду, что нам нужен действительный токен доступа (который хранится в HTTP-сеансе пользователя в нашем пограничном узле) для доступа к конечной точке нашего ресурса. Сервер.

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

В этой статье мы объяснили различия между аннотациями @EnableOAuth2Sso и @EnableResourceServer. Мы также продемонстрировали, как их использовать, на практическом примере с использованием Zuul и простого API.

Полную реализацию этого примера можно найти на Github.

При локальном запуске мы можем запустить и протестировать приложение по адресу http://192.168.1.67:8765/resource-server-mvc-1