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

Использование JWT с Spring Security OAuth (устаревший стек)

Руководство по использованию веб-токенов JSON с симметричной и асимметричной подписью в Spring Security OAuth.

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

1. Обзор

В этом уроке мы обсудим, как заставить нашу реализацию Spring Security OAuth2 использовать веб-токены JSON.

Мы также продолжаем развивать предыдущую статью в этой серии OAuth.

Прежде чем мы начнем – одно важное замечание. Имейте в виду, что команда Spring Security core находится в процессе внедрения нового стека OAuth2 – некоторые аспекты уже разработаны, а некоторые все еще находятся в процессе разработки.

Для версии этой статьи, использующей новый стек Spring Security 5, ознакомьтесь с нашей статьей, использующей JWT с Spring Security OAuth .

Хорошо, давайте сразу перейдем к делу.

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

Во-первых, нам нужно добавить spring-security-jwt зависимость к вашему pom.xml :


    org.springframework.security
    spring-security-jwt

Обратите внимание, что нам нужно добавить spring-security-jwt зависимость как для Сервера авторизации, так и для Сервера ресурсов.

3. Сервер авторизации

Затем мы настроим наш сервер авторизации для использования JwtTokenStore – следующим образом:

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) 
      throws Exception {
        endpoints.tokenStore(tokenStore())
                 .accessTokenConverter(accessTokenConverter())
                 .authenticationManager(authenticationManager);
    }

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("123");
        return converter;
    }

    @Bean
    @Primary
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        defaultTokenServices.setSupportRefreshToken(true);
        return defaultTokenServices;
    }
}

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

4. Сервер ресурсов

Теперь давайте взглянем на конфигурацию нашего Сервера ресурсов, которая очень похожа на конфигурацию Сервера авторизации:

@Configuration
@EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(ResourceServerSecurityConfigurer config) {
        config.tokenServices(tokenServices());
    }

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("123");
        return converter;
    }

    @Bean
    @Primary
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        return defaultTokenServices;
    }
}

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

5. Пользовательские утверждения в токене

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

Мы определим TokenEnhancer для настройки нашего токена доступа с помощью этих дополнительных утверждений.

В следующем примере мы добавим дополнительное поле ” organization ” к нашему маркеру доступа – с помощью этого CustomTokenEnhancer :

public class CustomTokenEnhancer implements TokenEnhancer {
    @Override
    public OAuth2AccessToken enhance(
      OAuth2AccessToken accessToken, 
      OAuth2Authentication authentication) {
        Map additionalInfo = new HashMap<>();
        additionalInfo.put(
          "organization", authentication.getName() + randomAlphabetic(4));
        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(
          additionalInfo);
        return accessToken;
    }
}

Затем мы подключим это к нашему Серверу авторизации конфигурации – следующим образом:

@Override
public void configure(
  AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
    tokenEnhancerChain.setTokenEnhancers(
      Arrays.asList(tokenEnhancer(), accessTokenConverter()));

    endpoints.tokenStore(tokenStore())
             .tokenEnhancer(tokenEnhancerChain)
             .authenticationManager(authenticationManager);
}

@Bean
public TokenEnhancer tokenEnhancer() {
    return new CustomTokenEnhancer();
}

С этой новой конфигурацией и запущенной – вот как будет выглядеть полезная нагрузка токена токена:

{
    "user_name": "john",
    "scope": [
        "foo",
        "read",
        "write"
    ],
    "organization": "johnIiCh",
    "exp": 1458126622,
    "authorities": [
        "ROLE_USER"
    ],
    "jti": "e0ad1ef3-a8a5-4eef-998d-00b26bc2c53f",
    "client_id": "fooClientIdPassword"
}

5.1. Используйте Маркер доступа в Клиенте JS

Наконец, мы хотим использовать информацию о токенах в нашем клиентском приложении Angularjs. Для этого мы будем использовать библиотеку angular-jwt .

Итак, что мы собираемся сделать, так это использовать утверждение ” организация ” в вашем index.html :