spring-security-oauth2-authorization-server(一)SpringBoot3.1.3整合
作者:mmseoamin日期:2023-12-18

文章目录

  • 写在前面的话
  • 1. 集成环境
  • 2. 了解OAuth2.1和Spring Authorization Server
    • 2.1 OAuth2.1
    • 2.2 spring-security-oauth2-authorization-server
    • 3. 项目搭建
      • 3.1 认证服务器框架搭建
      • 3.2 初始化自带的数据表
      • 3.3 验证核心配置AuthorizationServerConfig
        • 3.3.1 用于协议端点的Spring Security过滤器链
        • 3.3.2 用于认证的Spring Security过滤器链
        • 3.3.3 UserDetailsService 的一个实例,用于检索要认证的用户。
        • 3.3.4 RegisteredClientRepository 的一个实例,用于管理客户端
        • 3.3.5 配置解析JWT access-token的解析器
        • 3.3.6 AuthorizationServerSettings的一个实例,用于配置Spring授权服务器
        • 3.3.7 配置数据源信息
        • 3.4 启动项目
          • 3.4.1 访问/oauth2/authorize前往登录页面
          • 3.4.2 登录成功后跳转授权页面

            写在前面的话

            因为SpringBoot3.x是目前最新的版本,整合spring-security-oauth2-authorization-server的资料很少,所以产生了这篇文章,主要为想尝试SpringBoot高版本,想整合最新的spring-security-oauth2-authorization-server的初学者,旨在为大家提供一个简单上手的参考,如果哪里写得不对或可以优化的还请大家踊跃评论指正。

            1. 集成环境

            JDK-17
            spring-boot-dependencies-3.1.3
            spring-security-oauth2-authorization-server-1.1.2
            此文章主要参照官方文档编写,所有配置都能在官方文档上找到。
            https://docs.spring.io/spring-authorization-server/docs/current/reference/html/getting-started.html
            

            2. 了解OAuth2.1和Spring Authorization Server

            2.1 OAuth2.1

            关于OAuth2.1的介绍和规范可以参考官方文档:https://datatracker.ietf.org/doc/html/rfc6749#section-1

            2.2 spring-security-oauth2-authorization-server

            概述取自官方文档:

            Spring授权服务器是一个框架,提供 OAuth 2.1 和 OpenID Connect 1.0 规范及其他相关规范的实现。它建立在 Spring Security 之上,为构建OpenID Connect 1.0 Identity Provider 和OAuth2 授权服务器产品提供了一个安全、轻量级和可定制的基础。

            3. 项目搭建

            3.1 认证服务器框架搭建

            pom.xml

            
            
                4.0.0
                
                    org.springframework.boot
                    spring-boot-starter-parent
                    3.1.3
                    
                
                com.roshine
                authorization-server
                0.0.1-SNAPSHOT
                authorization-server
                authorization-server
                
                
                    17
                
                
                
                    
                        org.springframework.boot
                        spring-boot-starter-oauth2-authorization-server
                    
                    
                        mysql
                        mysql-connector-java
                        8.0.28
                    
                    
                        com.alibaba
                        druid-spring-boot-starter
                        1.2.19
                    
                    
                        com.baomidou
                        mybatis-plus-boot-starter
                        3.5.3.2
                    
                    
                        org.projectlombok
                        lombok
                        true
                    
                    
                        org.springframework.boot
                        spring-boot-starter-test
                        test
                    
                
                
                    
                        
                            org.springframework.boot
                            spring-boot-maven-plugin
                            
                                
                                    
                                        org.projectlombok
                                        lombok
                                    
                                
                            
                        
                    
                
            
            

            3.2 初始化自带的数据表

            • 已注册的客户端信息表
            • 认证授权表
            • 认证信息表

              spring-security-oauth2-authorization-server(一)SpringBoot3.1.3整合,在这里插入图片描述,第1张

              3.3 验证核心配置AuthorizationServerConfig

              改配置完全参照官方文档,内容如下

              3.3.1 用于协议端点的Spring Security过滤器链

              此处与官方文档略有不同:

              • 注释 .oidc(Customizer.withDefaults()),因为不清楚如何使用和验证,注释掉先
              • 默认前往登录页的uri是/login,如果需要自定义登录页可以改为自己的,这里我就暂时先用默认
                /**
                 * 用于协议端点的Spring Security过滤器链
                 *
                 * @param http HttpSecurity
                 * @return SecurityFilterChain
                 */
                @Bean
                public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
                    OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
                    http.getConfigurer(OAuth2AuthorizationServerConfigurer.class);
                            // 开启OpenID Connect 1.0 暂时不清楚该协议是什么,那就不用先
                            //.oidc(Customizer.withDefaults());
                    http
                            // 当未登录时访问认证端点时重定向至登录页面,默认前往登录页的uri是/login
                            .exceptionHandling((exceptions) -> exceptions
                                    .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")));
                    return http.build();
                }
                

                3.3.2 用于认证的Spring Security过滤器链

                 /**
                  * 用于认证的Spring Security过滤器链。
                  *
                  * @param http HttpSecurity
                  * @return SecurityFilterChain
                  */
                @Bean
                public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
                    http.authorizeHttpRequests((authorize) -> authorize
                                    .anyRequest().authenticated())
                            .formLogin(Customizer.withDefaults());
                    return http.build();
                }
                

                3.3.3 UserDetailsService 的一个实例,用于检索要认证的用户。

                /**
                 * 配置密码解析器,使用BCrypt的方式对密码进行加密和验证
                 *
                 * @return BCryptPasswordEncoder
                 */
                @Bean
                public PasswordEncoder passwordEncoder() {
                    return new BCryptPasswordEncoder();
                }
                @Bean
                public UserDetailsService userDetailsService() {
                    UserDetails userDetails = User.withUsername("admin")
                            .password(passwordEncoder().encode("123456"))
                            .roles("admin")
                            .build();
                    return new InMemoryUserDetailsManager(userDetails);
                }
                

                3.3.4 RegisteredClientRepository 的一个实例,用于管理客户端

                如果客户端信息已经存在于数据库则使用,否则存入

                /**
                 * 	RegisteredClientRepository 的一个实例,用于管理客户端
                 *
                 * @param jdbcTemplate jdbcTemplate
                 * @param passwordEncoder passwordEncoder
                 * @return RegisteredClientRepository
                 */
                @Bean
                public RegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTemplate, PasswordEncoder passwordEncoder) {
                    RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
                            .clientId("oauth2-client")
                            .clientSecret(passwordEncoder.encode("123456"))
                            // 客户端认证基于请求头
                            .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
                            // 配置授权的支持方式
                            .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
                            .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
                            .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
                            .redirectUri("https://www.baidu.com")
                            .scope("user")
                            .scope("admin")
                            // 客户端设置,设置用户需要确认授权
                            .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
                            .build();
                    JdbcRegisteredClientRepository registeredClientRepository = new JdbcRegisteredClientRepository(jdbcTemplate);
                    RegisteredClient repositoryByClientId = registeredClientRepository.findByClientId(registeredClient.getClientId());
                    if (repositoryByClientId == null) {
                        registeredClientRepository.save(registeredClient);
                    }
                    return registeredClientRepository;
                }
                

                3.3.5 配置解析JWT access-token的解析器

                因为spring-security-oauth2-authorization-server默认使用JWT作为access-token,所以需要添加此配置

                /**
                 * com.nimbusds.jose.jwk.source.JWKSource 的一个实例,用于签署访问令牌(access token)
                 *
                 * @return JWKSource
                 */
                @Bean
                public JWKSource jwkSource() {
                    KeyPair keyPair = generateRsaKey();
                    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
                    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
                    RSAKey rsaKey = new RSAKey.Builder(publicKey)
                            .privateKey(privateKey)
                            .keyID(UUID.randomUUID().toString())
                            .build();
                    JWKSet jwkSet = new JWKSet(rsaKey);
                    return new ImmutableJWKSet<>(jwkSet);
                }
                /**
                 * java.security.KeyPair 的一个实例,其 key 在启动时生成,用于创建上述 JWKSource。
                 *
                 * @return KeyPair
                 */
                private static KeyPair generateRsaKey() {
                    KeyPair keyPair;
                    try {
                        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
                        keyPairGenerator.initialize(2048);
                        keyPair = keyPairGenerator.generateKeyPair();
                    }
                    catch (Exception ex) {
                        throw new IllegalStateException(ex);
                    }
                    return keyPair;
                }
                /**
                 * JwtDecoder 的一个实例,用于解码签名访问令牌(access token)
                 *
                 * @param jwkSource jwkSource
                 * @return JwtDecoder
                 */
                @Bean
                public JwtDecoder jwtDecoder(JWKSource jwkSource) {
                    return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
                }
                

                3.3.6 AuthorizationServerSettings的一个实例,用于配置Spring授权服务器

                此处还是走默认配置

                @Bean 
                public AuthorizationServerSettings authorizationServerSettings() {
                	return AuthorizationServerSettings.builder().build();
                }
                

                3.3.7 配置数据源信息

                server:
                  port: 8080
                spring:
                  datasource:
                    driver-class-name: com.mysql.cj.jdbc.Driver
                    type: com.zaxxer.hikari.HikariDataSource
                    url: jdbc:mysql://xxx:3306/adp_bmc?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
                    username: xxx
                    password: xxx
                

                3.4 启动项目

                会看到oauth2_registered_client表写入了我们硬性配置的客户端信息

                spring-security-oauth2-authorization-server(一)SpringBoot3.1.3整合,在这里插入图片描述,第2张

                3.4.1 访问/oauth2/authorize前往登录页面

                http://127.0.0.1:8080/oauth2/authorize?client_id=oauth2-client&response_type=code&scope=user&redirect_uri=https://www.baidu.com

                spring-security-oauth2-authorization-server(一)SpringBoot3.1.3整合,在这里插入图片描述,第3张

                3.4.2 登录成功后跳转授权页面

                spring-security-oauth2-authorization-server(一)SpringBoot3.1.3整合,在这里插入图片描述,第4张

                授权完成后,跳转了我们的认证成功回调地址

                spring-security-oauth2-authorization-server(一)SpringBoot3.1.3整合,在这里插入图片描述,第5张

                获取到授权码我们就可以访问/oauth2/token获取JWT token了

                spring-security-oauth2-authorization-server(一)SpringBoot3.1.3整合,在这里插入图片描述,第6张

                这是一篇纯基础搭建的文章,主要参考自官方文档,官方文档才是新技术的根本。

                下一篇文章《spring-security-oauth2-authorization-server(二)token生成策略分析》会结合部分源码简要分析token几种生成策略。