springboot 2.7 oauth server配置源码走读一

2024-01-04 14:20

本文主要是介绍springboot 2.7 oauth server配置源码走读一,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

springboot 2.7 oauth server配置源码走读

入口:
在这里插入图片描述
上述截图中的方法签名和OAuth2AuthorizationServerConfiguration类中的一个方法一样,只不过我们自己的配置类优先级比spring中的配置类低,算是配置覆盖,看下图所示:
在这里插入图片描述
它们都提到了 OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
所以我们分析它:
在这里插入图片描述
一. new出来的OAuth2AuthorizationServerConfigurer:
官方声称它是:An AbstractHttpConfigurer for OAuth 2.0 Authorization Server support.(一个用于OAuth 2.0 授权服务器的抽象配置类)。
从源码中可以看到它“管理”着以下具体配置类:
在这里插入图片描述
先给出结论:这些配置类endpoint访问默认值对应如下(如何推导请耐心往下看):
在这里插入图片描述
我们具体看下上述第77行:getRequestMatcher(OAuth2TokenEndpointConfigurer.class).matches(request) 的实现:
我们可以看到第一条绿色下划线:tokenEndpoint的来源,等下我们再去探究它:
在这里插入图片描述
所以我们去AntPathRequestMatcher类 查看实现:
可以看到用到了策略模式:根据pattern (/**表示MATCH_ALL)不同,初始化的matcher也不同:
在这里插入图片描述
接下来我们可以看上述第一条绿色下划线:tokenEndpoint的来源,现在去探究它:

ProviderSettings:它是一个配置类,继承于AbstractSettings(接下来我们自己配置中用到的TokenSettings+ClientSettings类也继承于它),如下所求,我们可以指定token endpoint(当然还有授权,introspection等等),
在这里插入图片描述

如果不指定,则默认配置如下:注意 /oauth2/jwks, 后面resource-server就可以指定它来验证token的有效性。
在这里插入图片描述

那ProvideSettings如何初始化呢?又是和配置类关联起来?
1.构造方法中传递:
在这里插入图片描述
2.在我们的配置类中流入bean(官方示例也是这么做的):
在这里插入图片描述

然后看源码:
在这里插入图片描述

其中providerSettings.getJwkSetEndpoint()我们上面看过,如果没有指定配置,则默认值为:
/oauth2/jwks
在这里插入图片描述
二. 我们配置类中的其它配置:
在这里插入图片描述
上述2个配置方法在OAuth2AuthorizationServerConfiguration类中也可以找到类似的方法,如下所示:
在这里插入图片描述
三.最后把完整的oauth2 server配置如下:

package com.jel.tech.auth.config;import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.config.ClientSettings;
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.time.Duration;
import java.util.UUID;/*** @author: jelex.xu* @Date: 2024/1/2 18:31* @desc:**/
@Configuration
public class OAuth2AuthorizeSecurityConfig {/*** 重写:org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration*          #authorizationServerSecurityFilterChain(HttpSecurity)* @param http* @return* @throws Exception*/@Bean@Order(1)public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);return http.formLogin(Customizer.withDefaults()).build();}@Bean@Order(2)public SecurityFilterChain standardSecurityFilterChain(HttpSecurity http) throws Exception {// @formatter:offhttp.authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated()).formLogin(Customizer.withDefaults());// @formatter:onreturn http.build();}@Beanpublic RegisteredClientRepository registeredClientRepository() {RegisteredClient loginClient = RegisteredClient.withId(UUID.randomUUID().toString()).clientId("login-client").clientSecret("{noop}openid-connect").clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC).authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN).redirectUri("http://127.0.0.1:8080/login/oauth2/code/login-client").redirectUri("http://127.0.0.1:8080/authorized").scope(OidcScopes.OPENID).scope(OidcScopes.PROFILE).clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build()).build();RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString()).clientId("messaging-client").clientSecret("{noop}secret").clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC).authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).scope("message:read").scope("message:write")// 指定token有效期:token:30分(默认5分钟),refresh_token:1天.tokenSettings(TokenSettings.builder().accessTokenTimeToLive(Duration.ofMinutes(30)).refreshTokenTimeToLive(Duration.ofDays(1)).build())
//                .id("xxx").build();return new InMemoryRegisteredClientRepository(loginClient, registeredClient);}@Beanpublic JWKSource<SecurityContext> jwkSource(KeyPair keyPair) {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);}@Beanpublic JwtDecoder jwtDecoder(KeyPair keyPair) {return NimbusJwtDecoder.withPublicKey((RSAPublicKey) keyPair.getPublic()).build();}@Beanpublic ProviderSettings providerSettings() {return ProviderSettings.builder().issuer("http://127.0.0.1:9000").build();}@Beanpublic UserDetailsService userDetailsService() {PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();// outputs {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG// remember the password that is printed out and use in the next stepSystem.out.println(encoder.encode("password"));UserDetails userDetails = User.withUsername("user").username("user").password("{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG").roles("USER").build();return new InMemoryUserDetailsManager(userDetails);}@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)KeyPair generateRsaKey() {KeyPair keyPair;try {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");keyPairGenerator.initialize(2048);keyPair = keyPairGenerator.generateKeyPair();return keyPair;} catch (NoSuchAlgorithmException e) {throw new IllegalArgumentException(e);}}
}

这篇关于springboot 2.7 oauth server配置源码走读一的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/569607

相关文章

java使用protobuf-maven-plugin的插件编译proto文件详解

《java使用protobuf-maven-plugin的插件编译proto文件详解》:本文主要介绍java使用protobuf-maven-plugin的插件编译proto文件,具有很好的参考价... 目录protobuf文件作为数据传输和存储的协议主要介绍在Java使用maven编译proto文件的插件

Jenkins分布式集群配置方式

《Jenkins分布式集群配置方式》:本文主要介绍Jenkins分布式集群配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1.安装jenkins2.配置集群总结Jenkins是一个开源项目,它提供了一个容易使用的持续集成系统,并且提供了大量的plugin满

Java中的数组与集合基本用法详解

《Java中的数组与集合基本用法详解》本文介绍了Java数组和集合框架的基础知识,数组部分涵盖了一维、二维及多维数组的声明、初始化、访问与遍历方法,以及Arrays类的常用操作,对Java数组与集合相... 目录一、Java数组基础1.1 数组结构概述1.2 一维数组1.2.1 声明与初始化1.2.2 访问

Javaee多线程之进程和线程之间的区别和联系(最新整理)

《Javaee多线程之进程和线程之间的区别和联系(最新整理)》进程是资源分配单位,线程是调度执行单位,共享资源更高效,创建线程五种方式:继承Thread、Runnable接口、匿名类、lambda,r... 目录进程和线程进程线程进程和线程的区别创建线程的五种写法继承Thread,重写run实现Runnab

Java 方法重载Overload常见误区及注意事项

《Java方法重载Overload常见误区及注意事项》Java方法重载允许同一类中同名方法通过参数类型、数量、顺序差异实现功能扩展,提升代码灵活性,核心条件为参数列表不同,不涉及返回类型、访问修饰符... 目录Java 方法重载(Overload)详解一、方法重载的核心条件二、构成方法重载的具体情况三、不构

Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式

《Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式》本文详细介绍如何使用Java通过JDBC连接MySQL数据库,包括下载驱动、配置Eclipse环境、检测数据库连接等关键步骤,... 目录一、下载驱动包二、放jar包三、检测数据库连接JavaJava 如何使用 JDBC 连接 mys

SpringBoot线程池配置使用示例详解

《SpringBoot线程池配置使用示例详解》SpringBoot集成@Async注解,支持线程池参数配置(核心数、队列容量、拒绝策略等)及生命周期管理,结合监控与任务装饰器,提升异步处理效率与系统... 目录一、核心特性二、添加依赖三、参数详解四、配置线程池五、应用实践代码说明拒绝策略(Rejected

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注

Java操作Word文档的全面指南

《Java操作Word文档的全面指南》在Java开发中,操作Word文档是常见的业务需求,广泛应用于合同生成、报表输出、通知发布、法律文书生成、病历模板填写等场景,本文将全面介绍Java操作Word文... 目录简介段落页头与页脚页码表格图片批注文本框目录图表简介Word编程最重要的类是org.apach

Spring Boot中WebSocket常用使用方法详解

《SpringBoot中WebSocket常用使用方法详解》本文从WebSocket的基础概念出发,详细介绍了SpringBoot集成WebSocket的步骤,并重点讲解了常用的使用方法,包括简单消... 目录一、WebSocket基础概念1.1 什么是WebSocket1.2 WebSocket与HTTP