Spring Authorization Server 全新授权服务器整合使用
阅读原文时间:2022年03月26日阅读:1
  • Spring Authorization Server 是 Spring 团队最新开发适配 OAuth 协议的授权服务器项目,旨在替代原有的 Spring Security OAuth

  • 经过半年的开发和孵化,目前已经发布了 0.1.0 版本,初步支持授权码、客户端、刷新、注销等 OAuth 协议

  • 本文环境基于 Spring Boot 2.4.2 && authorization-server 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 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' <br /> --header 'Authorization: Basic cGlnOnBpZw==' <br /> --header 'Content-Type: application/x-www-form-urlencoded' <br /> --data-urlencode 'token={access_token}' <br /> --data-urlencode 'token_type_hint=access_token'

  • 通过 refresh_token

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

  • RegisteredClient 支持个性化 token 设置的入参

    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;
    }
  • 本节源码: https://github.com/lltx/auth-server-demo

  • 由于官方暂时未完善相关的文档,所有的端点入参等需要参考 The OAuth 2.0 Authorization Framework

>>> 源码 https://gitee.com/log4j/pig,欢迎署名转载 <<<