spring-security-oauth2-authorization-server(一)SpringBoot3.1.3整合

本文详细介绍了如何在SpringBoot3.1.3版本中集成并配置最新版本的spring-security-oauth2-authorization-server,包括环境配置、项目结构、数据表初始化、核心配置及启动流程,为初学者提供一个入门指南。
摘要由CSDN通过智能技术生成

写在前面的话

因为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

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.3</version>
        <relativePath/>
    </parent>
    <groupId>com.roshine</groupId>
    <artifactId>authorization-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>authorization-server</name>
    <description>authorization-server</description>
    
    <properties>
        <java.version>17</java.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-authorization-server</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.19</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.2</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

3.2 初始化自带的数据表

  • 已注册的客户端信息表
  • 认证授权表
  • 认证信息表
    在这里插入图片描述

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<SecurityContext> 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<SecurityContext> 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表写入了我们硬性配置的客户端信息
在这里插入图片描述

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
在这里插入图片描述

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

在这里插入图片描述
授权完成后,跳转了我们的认证成功回调地址
在这里插入图片描述
获取到授权码我们就可以访问/oauth2/token获取JWT token了
在这里插入图片描述
这是一篇纯基础搭建的文章,主要参考自官方文档,官方文档才是新技术的根本。
下一篇文章《spring-security-oauth2-authorization-server(二)token生成策略分析》会结合部分源码简要分析token几种生成策略。

Spring Boot Starter Security是一个轻量级的框架,用于快速集成Spring Security到Spring Boot应用程序中。版本3.3.4提供了一系列的安全功能,包括身份验证、授权、会话管理等。以下是使用Spring Boot Starter Security的一个简单教程: 1. **添加依赖**: 在你的`pom.xml`或`build.gradle`文件中添加Spring Security的相关依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> ``` 2. **配置应用安全**: 创建一个`SecurityConfig.java`类并实现WebSecurityConfigurerAdapter,设置默认的登录页面和注销路径: ```java import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/", "/login").permitAll() .anyRequest().authenticated() .and() .formLogin().loginPage("/login") .logout().logoutUrl("/logout"); } // 如果需要,可以在此配置用户认证 @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("user").password("{noop}password").roles("USER"); } } ``` 3. **创建登录界面**: 创建一个简单的HTML登录表单,并将其放在`src/main/resources/static/login.html`文件中。 4. **启动应用**: 使用Spring Boot命令行工具运行应用,访问`http://localhost:8080/login`尝试登录。 5. **自定义授权规则**: 如果你需要更复杂的权限控制,可以在`configure()`方法中使用`accessDecisionManager()`,或者使用基于注解的声明式安全控制。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值