Spring Authorization Server новый интегрированный сервер авторизации

Spring Boot Java

предисловие

  • Spring Authorization Server — это последний проект сервера авторизации, разработанный командой Spring для адаптации протокола OAuth с целью замены оригинального Spring Security OAuth.

  • После полугода разработки и инкубации была выпущена версия 0.1.0, первоначально поддерживающая протоколы OAuth, такие как код авторизации, клиент, обновление, выход из системы и т. д.

  • Среда этой статьи основана на Spring Boot 2.4.2 и сервере авторизации 0.1.0.

Сборка сервера

1. maven-зависимости

<!--oauth2 server-->
<dependency>
  <groupId>org.springframework.security.experimental</groupId>
  <artifactId>spring-security-oauth2-authorization-server</artifactId>
  <version>0.1.0</version>
</dependency>
<!--security dependency-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2. Инициализируйте конфигурацию

  • Поскольку официальный представитель не предоставил соответствующую автоматическую настройку Spring Boot Starter, вам необходимо настроить соответствующий @Bean самостоятельно.
  • Эта конфигурация основана на Spring Boot 2.4.2 Пожалуйста, знайте
@Configuration
@EnableWebSecurity
@Import(OAuth2AuthorizationServerConfiguration.class)
public class AuthServerConfiguration {

 //  定义 spring security 拦击链规则
 @Bean
 SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
  http
    .authorizeRequests(authorizeRequests ->
      authorizeRequests.anyRequest().authenticated()
    )
    .formLogin(withDefaults());
  return http.build();
 }

  // 创建默认登录用户 lengleng / 123456
 @Bean
 public UserDetailsService userDetailsService() {
  UserDetails userDetails = User.builder()
    .username("lengleng")
    .password("{noop}123456")
    .authorities("ROLE_USER")
    .build();
  return new InMemoryUserDetailsManager(userDetails);
 }

  // 创建默认的bean 登录客户端,基于 授权码、 刷新令牌的能力
 @Bean
 public RegisteredClientRepository registeredClientRepository() {
  RegisteredClient client = RegisteredClient.withId("pig")
    .clientId("pig")
    .clientSecret("pig")
    .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC)
    .authorizationGrantTypes(authorizationGrantTypes -> {
     authorizationGrantTypes.add(AuthorizationGrantType.AUTHORIZATION_CODE);
     authorizationGrantTypes.add(AuthorizationGrantType.REFRESH_TOKEN);
    })
    .redirectUri("https://pig4cloud.com")
    .build();
  return new InMemoryRegisteredClientRepository(client);
 }


  // 指定token 生成的加解密密钥
 @Bean
 @SneakyThrows
 public JWKSource<SecurityContext> jwkSource() {
  KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
  keyPairGenerator.initialize(2048);
  KeyPair keyPair = keyPairGenerator.generateKeyPair();
  RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
  RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

  // @formatter:off
  RSAKey rsaKey= new RSAKey.Builder(publicKey)
    .privateKey(privateKey)
    .keyID(UUID.randomUUID().toString())
    .build();
  JWKSet jwkSet = new JWKSet(rsaKey);
  return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
 }
}

тестовое задание

Аутентификация кода авторизации

curl --location --request GET 'http://localhost:3000/oauth2/authorize?client_id=pig&client_secret=pig&response_type=code&redirect_uri=https://pig4cloud.com'

получить токен

curl --location --request POST 'http://localhost:3000/oauth2/token' \
--header 'Authorization: Basic cGlnOnBpZw==' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'code={code}' \
--data-urlencode 'redirect_uri=https://pig4cloud.com'

обновить токен

curl --location --request POST 'http://localhost:3000/oauth2/token' \
--header 'Authorization: Basic cGlnOnBpZw==' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token={refresh_token}' \

токен отзыва

  • через access_token
curl --location --request POST 'http://localhost:3000/oauth2/revoke' \
--header 'Authorization: Basic cGlnOnBpZw==' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'token={access_token}' \
--data-urlencode 'token_type_hint=access_token'
  • через refresh_token
curl --location --request POST 'http://localhost:3000/oauth2/revoke' \
--header 'Authorization: Basic cGlnOnBpZw==' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'token={refresh_token}' \
--data-urlencode 'token_type_hint=refresh_token'

Расширение содержимого | Персонализация токена

  • RegisteredClient поддерживает входные параметры для персонализированных настроек токена.
RegisteredClient..tokenSettings()
  • Конфигурация по умолчанию выглядит следующим образом, включая срок действия токена, управление токеном обновления и т. д.
 protected static Map<String, Object> defaultSettings() {
  Map<String, Object> settings = new HashMap<>();
  settings.put(ACCESS_TOKEN_TIME_TO_LIVE, Duration.ofMinutes(5));
  settings.put(REUSE_REFRESH_TOKENS, true);
  settings.put(REFRESH_TOKEN_TIME_TO_LIVE, Duration.ofMinutes(60));
  return settings;
 }

Суммировать