Микросервисы и Spring Безопасность OAuth2

У меня уже есть сервер авторизации OAuth2, работающий в другом проекте. Теперь мне нужно будет защитить несколько простых серверов spring -boot-rest с OAuth2. Но я нахожу Spring документацию действительно очень ограниченную, когда дело доходит до разделения серверов авторизации и ресурсов.

Я также нашел несколько вопросов, где ответ был "Ну, они могут быть разными, если они используют один и тот же файл данных tokenStore". Неужели это правда? Как это могло случиться для микросервисов? Казалось бы, действительно странно, что каждый сервис отдыха должен будет реализовать свой собственный сервер авторизации OAuth.

Итак, как мне настроить защиту Oauth2.0 для spring -boot rest-endpoints, которые ссылаются на удаленный сервер авторизации oauth (возможно, даже не написанный с помощью Spring)?

Там эта вещь называется RemoteTokenServices, которая кажется многообещающей, но она вообще не документирована.

Ответ 1

При настройке сервера auh::

Создайте новый clientDetails в ClientDetailsServiceConfigurer для сервера ресурсов. который будет использоваться для настройки RemoteTokenService.

Настроить Spring Безопасность OAuth2 на сервере ресурсов:

Создайте класс, который аннотируется с помощью @EnableWebSecurity, @Configuration и расширяет WebSecurityConfigurerAdapter.

@Configuration
@EnableWebSecurity
protected static class ResourceConfiguration extends WebSecurityConfigurerAdapter {
  // methods        
}

Создайте метод с @ Bean аннотированным, который вернет экземпляр TokenService, который будет использоваться для создания AuthenticationManager.

В этом методе создайте экземпляр RemoteTokenService и установите clientId, client_secret, checkTokenEndpointUrl и DefaultAccessTokenConverterWithClientRoles (этот класс является нашей реализацией, чтобы получить client_authority при аутентификации accessToken на сервере OAuth2.)

@Bean
public ResourceServerTokenServices tokenService() {
    RemoteTokenServices tokenServices = new RemoteTokenServices();
    tokenServices.setClientId("resource_id");
    tokenServices.setClientSecret("resource_secret");
    tokenServices.setCheckTokenEndpointUrl("http://<server-url>: <port>/oauth/check_token");
    return tokenServices;
}

Переопределите метод authenticationManagerBean() и аннотируйте его с помощью @Bean и верните экземпляр OAuth2AuthenticationManager с TokenService.

@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
    OAuth2AuthenticationManager authenticationManager = new OAuth2AuthenticationManager();
    authenticationManager.setTokenServices(tokenService());
    return authenticationManager;
}

Создайте класс, аннотированный с помощью @EnableResourceServer, @Configuration и продолжите ResourceServerConfigurerAdapter.

@Configuration
@EnableResourceServer
protected static class ResourceServerConfig extends ResourceServerConfigurerAdapter {
  // Mehotds
}

Переопределить методы настройки - это суперкласс для настройки сервера ресурсов. Различные настройки для настройки сервера ресурсов.

ResourceServerSecurityConfigurer: для настройки Resource_id.

HttpSecurity. Это позволит настроить фильтр безопасности, чтобы сообщить, что пользователю требуется аутентификация для защищенных URL-адресов (API).

@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
    resources.resourceId("resource_id");
}

@Override
public void configure(HttpSecurity http) throws Exception {
    // @formatter:off
    http
     .authorizeRequests()
     .antMatchers("/**").authenticated()
     .and()
     .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    // @formatter:on
}

.antMatcher("/**").authenticated() эта строка будет защищать каждый URL вашего сервера ресурсов. .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) не будет создавать сеанс.

PS:: Если что-то не так, скажите мне.

Ответ 2

Не правда, что обе они должны иметь одну и ту же базу данных, если сервер ресурсов имеет некоторый способ проверки подлинности маркера доступа (был выпущен сервером авторизации), а также каким-то способом его декодирования (может потребоваться чтобы узнать, какие области он предоставляет, например). Спецификация OAuth2 ничего не говорит о том, как это должно быть достигнуто.

Если ресурс находится в том же процессе, что и сервер авторизации, то совместное использование данных является простым вариантом. В противном случае ему нужен способ перевода токена. Если токен - это просто непрозрачная строка случайных байтов, то, очевидно, он должен обменивать его на реальную информацию. Это то, что делает RemoteTokenServices. Сервер авторизации предоставляет конечную точку /check_token, позволяющую декодировать токены.

Альтернативой является фактическое кодирование информации в токене и авторизация сервера авторизации. Сервер ресурсов может затем декодировать и проверять сам токен, пока он понимает формат.

Я бы рекомендовал вам взглянуть на Cloudfoundry UAA, который предоставляет сервер авторизации из коробки, которая реализована с использованием подписанных токенов JWT (он также предоставляет конечную точку /check_token). Обзор токенов и API docs, вероятно, являются хорошим началом точка.

Ответ 3

Рабочий образец RemoteTokenService можно найти здесь.

Подробнее о check_token api можно узнать org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint.java

На сервере ресурса OAuth2AuthenticationProcessingFilter проверяет токен OAuth2, вызывая метод OAuth2AuthenticationManager.authenticate(), который заставляет вызов RemoteTokenServices.loadAuthentication() проверять токен с сервера Auth.