行业知识
spring-security-oauth2-authorization-server(一)SpringBoot3.1.3整合
文章目录
- 写在前面的话
- 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-17spring-boot-dependencies-3.1.3spring-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 初始化自带的数据表
- 已注册的客户端信息表
- 认证授权表
- 认证信息表
3.3 验证核心配置AuthorizationServerConfig
改配置完全参照官方文档,内容如下
3.3.1 用于协议端点的Spring Security过滤器链
此处与官方文档略有不同:
- 注释 .oidc(Customizer.withDefaults()),因为不清楚如何使用和验证,注释掉先
- 默认前往登录页的uri是/login,如果需要自定义登录页可以改为自己的,这里我就暂时先用默认
/** * 用于协议端点的Spring Security过滤器链 * * @param http HttpSecurity * @return SecurityFilterChain */@Beanpublic 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 */@Beanpublic 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 */@Beanpublic PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder();}@Beanpublic 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 */@Beanpublic 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 */@Beanpublic 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 */@Beanpublic 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: 8080spring: 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几种生成策略。
下一篇:服务器怎么写我的世界?