OAuth2 - @EnableResourceServer vs @ EnableOAuth2Sso

OAuth2 - @EnableResourceServer vs @ EnableOAuth2Sso

1. обзор

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

Начнем с объясненияdifferences between an OAuth2 Client and an OAuth2 Resource Server. После этого мы немного поговорим о том, что эти аннотации могут для нас сделать, и продемонстрируем их использование на примере с использованиемZuul и простого API.

Для целей этой статьи мы будем предполагать некоторый ранее существовавший опыт работы сZuul иOAuth2.

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

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

В OAuth2 необходимо учитывать четыре разныхroles:

  • Resource Owner - объект, который может предоставить доступ к своим защищенным ресурсам

  • Authorization Server - предоставляет токены доступаClients после успешной аутентификацииResourceOwners и получения их авторизации

  • Resource Server - компонент, которому требуется токен доступа для разрешения или, по крайней мере, возможности доступа к его ресурсам

  • Client - сущность, способная получать токены доступа от серверов авторизации

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

The @EnableResourceServer annotation enables our application to behave as a Resource Server, настроивOAuth2AuthenticationProcessingFilter и другие не менее важные компоненты.

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

Наоборот,the @EnableOAuth2Sso annotation transforms our application into an OAuth2 client. Он инструктирует Spring настроитьOAuth2ClientAuthenticationProcessingFilter вместе с другими компонентами, которые необходимы нашему приложению для получения токенов доступа с сервера авторизации.

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

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

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

  • Второе приложение будет использовать аннотацию@EnableResourceServer и разрешит доступ к защищенным ресурсам, если входящие запросы содержат действительный токен доступа OAuth2.

3. Зуул -@EnableOAuth2Sso

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

@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. Это сделано для того, чтобы гарантировать, чтоFilters, созданные нашимWebSecurityConfigurerAdapter, имеют приоритет надFilters, созданным другимиWebSecurityConfigurerAdapters.

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

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

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 для нашего приложения, чтобы иметь возможность взаимодействовать с нашимAuthorizationServer, и настройкаJWT с шифрованиемsymmetric.

4. API -@EnableResourceServer

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

@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();
    }
}

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

В заключение, настроим некоторые свойства:

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

Имейте в виду, чтоwe need a valid access token (который хранится в HTTP-сеансе пользователя в нашем пограничном узле)to access the endpoint of our Resource Server.

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

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

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

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