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

Новое в Spring Security OAuth2 – Проверка утверждений

Быстрое практическое введение в новую поддержку проверки утверждений в Spring Security OAuth.

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

1. Обзор

В этом кратком руководстве мы будем работать с реализацией Spring Security OAuth2 и узнаем, как проверить утверждения JWT с помощью нового JwtClaimsSetVerifier – введенного в Spring Security OAuth 2.2.0.RELEASE .

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

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


    org.springframework.security.oauth
    spring-security-oauth2
    2.2.0.RELEASE

3. Конфигурация хранилища Токенов

Далее, давайте настроим наше Хранилище токенов на сервере ресурсов:

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

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

Обратите внимание, как мы добавляем новый верификатор в наш JwtAccessTokenConverter .

Для получения более подробной информации о том , как настроить JwtTokenStore , ознакомьтесь с записью об использовании GWT с Spring Security OAuth .

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

4. Верификатор претензий Эмитента

Мы начнем с простого – с проверки утверждения эмитента ” iss ” с помощью IssuerClaimVerifier – следующим образом:

@Bean
public JwtClaimsSetVerifier issuerClaimVerifier() {
    try {
        return new IssuerClaimVerifier(new URL("http://localhost:8081"));
    } catch (MalformedURLException e) {
        throw new RuntimeException(e);
    }
}

В этом примере мы добавили простой Верификатор утверждений эмитента для проверки вашего эмитента. Если токен JWT содержит другое значение для утверждения “iss” эмитента, простой Будет выдано исключение InvalidTokenException .

Естественно, если токен действительно содержит утверждение эмитента “iss”, исключение не будет выдано, и токен считается действительным.

5. Пользовательский Верификатор Утверждений

Но что здесь интересно, так это то, что мы также можем создать свой собственный верификатор утверждений:

@Bean
public JwtClaimsSetVerifier customJwtClaimVerifier() {
    return new CustomClaimVerifier();
}

Вот простая реализация того, как это может выглядеть – проверить, существует ли утверждение user_name в нашем токене JWT:

public class CustomClaimVerifier implements JwtClaimsSetVerifier {
    @Override
    public void verify(Map claims) throws InvalidTokenException {
        String username = (String) claims.get("user_name");
        if ((username == null) || (username.length() == 0)) {
            throw new InvalidTokenException("user_name claim is empty");
        }
    }
}

Обратите внимание, как мы просто реализуем здесь интерфейс JwtClaimsSetVerifier , а затем предоставляем полностью настраиваемую реализацию метода verify, что дает нам полную гибкость для любого вида проверки, в которой мы нуждаемся.

6. Объедините Несколько Проверяющих Утверждений

Наконец, давайте посмотрим, как объединить несколько верификаторов утверждений с помощью DelegatingJwtClaimsSetVerifier – следующим образом:

@Bean
public JwtClaimsSetVerifier jwtClaimsSetVerifier() {
    return new DelegatingJwtClaimsSetVerifier(Arrays.asList(
      issuerClaimVerifier(), customJwtClaimVerifier()));
}

Делегирование Jwtclaimssetverifier берет список объектов Jwt Claims Set Verifier и делегирует процесс проверки утверждений этим верификаторам.

7. Простой Интеграционный тест

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

@RunWith(SpringRunner.class)
@SpringBootTest(
  classes = ResourceServerApplication.class, 
  webEnvironment = WebEnvironment.RANDOM_PORT)
public class JwtClaimsVerifierIntegrationTest {

    @Autowired
    private JwtTokenStore tokenStore;

    ...
}

Мы начнем с токена, который не содержит эмитента (но содержит имя пользователя ) – который должен быть действительным:

@Test
public void whenTokenDontContainIssuer_thenSuccess() {
    String tokenValue = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9....";
    OAuth2Authentication auth = tokenStore.readAuthentication(tokenValue);
    
    assertTrue(auth.isAuthenticated());
}

Причина, по которой это допустимо, проста – первый верификатор активен только в том случае, если в токене существует утверждение эмитента. Если этого утверждения не существует – верификатор не срабатывает.

Далее давайте посмотрим на токен, который содержит действительного эмитента ( http://localhost:8081 ) и имя пользователя также. Это также должно быть действительным:

@Test
public void whenTokenContainValidIssuer_thenSuccess() {
    String tokenValue = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9....";
    OAuth2Authentication auth = tokenStore.readAuthentication(tokenValue);
    
    assertTrue(auth.isAuthenticated());
}

Если токен содержит недопустимого эмитента ( http://localhost:8082 ) – затем он будет проверен и признан недействительным:

@Test(expected = InvalidTokenException.class)
public void whenTokenContainInvalidIssuer_thenException() {
    String tokenValue = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9....";
    OAuth2Authentication auth = tokenStore.readAuthentication(tokenValue);
    
    assertTrue(auth.isAuthenticated());
}

Далее, если токен не содержит утверждения user_name , он будет недействительным:

@Test(expected = InvalidTokenException.class)
public void whenTokenDontContainUsername_thenException() {
    String tokenValue = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9....";
    OAuth2Authentication auth = tokenStore.readAuthentication(tokenValue);
    
    assertTrue(auth.isAuthenticated());
}

И, наконец, когда токен содержит пустое утверждение user_name , он также недействителен:

@Test(expected = InvalidTokenException.class)
public void whenTokenContainEmptyUsername_thenException() {
    String tokenValue = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9....";
    OAuth2Authentication auth = tokenStore.readAuthentication(tokenValue);
    
    assertTrue(auth.isAuthenticated());
}

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

В этой краткой статье мы рассмотрели новую функциональность верификатора в Spring Security OAuth.

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