oauth2-resource-server授权配置介绍

news/2024/11/17 0:44:12/

1、背景

当了解这篇文章授权服务器后,对授权服务器有一定的认识,那么授权服务器生成token后,该怎么用呢,这就涉及到资源服务器,现在给大家简单介绍实现过程。

2、方案

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-oauth2-resource-server</artifactId></dependency>

2.1 基于官网配置

首先先配置 issuer-uri ,这里指向是授权服务器的地址

# 授权服务器地址
spring.security.oauth2.resourceserver.jwt.issuer-uri= http://localhost:9000

关于过滤器链的配置:

@EnableWebSecurity
@Configuration(proxyBeanMethods = false)
public class ResourceServerConfig {// @formatter:off@BeanSecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.securityMatcher("/messages/**").authorizeHttpRequests().requestMatchers("/messages/**").hasAuthority("SCOPE_message.read").and().oauth2ResourceServer().jwt();return http.build();}// @formatter:on}

资源服务器将使用此 issuer-uri 进一步进行自我配置,发现授权服务器的公钥,并传入用于验证JWT的JwtDecoder。此过程的结果是授权服务器必须启动并接收请求才能使资源服务器成功启动。 

若如果资源服务器必须能够独立于授权服务器启动,那么可以提供jwk-set-uri。这将是我们进一步在OAuth2安全配置中添加属性:

# 资源服务器必须能够独立于授权服务器启动
spring.security.oauth2.resourceserver.jwt.jwk-set-uri= http://localhost:9000/oauth2/jwks

至此,资源服务器可以正常使用。若是你的系统比较庞大,每次请求都会请求授权服务器,这会给授权服务器带来压力,具体的实现方案可以根据实际情况而定。

2.2 确定加密方式

授权服务器的操作:

# JWK 配置
cloud:jwk:rsa:# 公钥public-key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzt2qx7HwpblnbwtRV9ZiaXwvUO4JlOYYVFEDmINxp5d+Nbih8hmOrlM+4qhr5Ej1Gc+D+TJ2oNoN/wtUaGP38Kf21UhiEbRedRfdQvOEuDXmScLUBd4tJ9dH4+i5XFSnkZi3L0rlTmPLpv8SuJSnNg/POjxmBxBAnJq4qmm2c7bXqcXOa8oAQYMtBHtuA6hhbbD2tpZEr4tM010eDPrZysFeVKNFlNV9fgBL5H2s7GRqVslHEmU6vQfQGCXL2Z+jDv8WH3k3kneV7EL24IipMDjmPzxk5zw6L8uzKxANuLVnh3mCDkqnaPMN4TBTSqE5muKR5SHyGF0/dqxodmanWwIDAQAB# 私钥private-key: MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDO3arHsfCluWdvC1FX1mJpfC9Q7gmU5hhUUQOYg3Gnl341uKHyGY6uUz7iqGvkSPUZz4P5Mnag2g3/C1RoY/fwp/bVSGIRtF51F91C84S4NeZJwtQF3i0n10fj6LlcVKeRmLcvSuVOY8um/xK4lKc2D886PGYHEECcmriqabZzttepxc5rygBBgy0Ee24DqGFtsPa2lkSvi0zTXR4M+tnKwV5Uo0WU1X1+AEvkfazsZGpWyUcSZTq9B9AYJcvZn6MO/xYfeTeSd5XsQvbgiKkwOOY/PGTnPDovy7MrEA24tWeHeYIOSqdo8w3hMFNKoTma4pHlIfIYXT92rGh2ZqdbAgMBAAECggEAHBX2GbO70lGdofLIQfk466JxLXc2tNEX94aiStgkcQESoR+RWTSFbdSejUPEQOkeNzljQnef/znBEbdg5+VpZHKhgsFCPgNzmZ6Pq1yIUJb8zldAgGVy/bLvBJn0ZKftB57+K/0VV0hu/hwpLLH+ESB3Xaw/8UXlx9KtL3Hifst94yMNh2+g1qHK7BIBxVlZmm8y137lt/ZJCCKf7zDOBFFmm/Hy71K7C6uOGmRmJ7Thq7f2dJx8iecPvMv7Bzd+LzvuZdJjowZkzMXPv85hUEpbToEQUHt4FReWWk87OUSRaXUZVONZvzUHMrYqN84tvONSa+swnxGWvjK2rRcSdQKBgQDyFeqQGPzJQY2u0rhMuj12yDTssSV7xagw88KYkaWpireuSEjxJpIEhRxjO3Ow0TYvZM9t7g/6gvuYh30/FIND4AwAuRtjAjKzXfOlIG7dJMBEk5yY1tloGwxak8sa8z+H+jw9cJik+X5j6MULNzUb709UPgMstxEVrCfhgEal/QKBgQDawYXIq1q43qIuFdjFOnZ6qBHtqWtIi8lZcOSUtPuqivIVSJt7AnkNhR9MfhkgaEuoL55wBR0BA+DoZWFmObgi5Y+Udb2+nlZVufY/ksNyZ1i+4ITKhzns7qjG2W0KMh7MG0biNbTtBy54WQp+Myog1UbuXMqyMSIunwRhOC5WNwKBgQDaDK+IN1mJlUgezaI/SgkOsmopP645e+Fwpj8C2T1UJqQnkOhSfaFL/PGC2AvumaKqsay8oY823z/rNS604K8TNfzZseFfHp24Pcm1VC9HdVDQ8/w7FlogkSxhcXmhvrPcsKIN3RtAjZEwQHsrDQEDNlxHzsthPUtgL/6D+NypqQKBgQDWN2Y8ENkBajrk6E3jLZHyIP2Vfy9o1kJxTKT6npRH+FKB1x0yg0Rpoe/5Zw5R9vAHncIILmmtoc+vo/+SLHmN6sEEf5w0uzcOMdHbhWvRbzSvjotbDLsDst4iA67MqjIQa7GpOTCYYEz4WzF0TcQ2bMRODR4NCyJPBzcxwONXVwKBgH8iJJtdmftjFqOkqNLT6XzLdPE4grkSzd2/RGiK003L3n0CxE2UqzNW/oSikAO5Jc/Tsxv6FtL9o/0Kjhut05C96Ku1oJfm7QI9ORSgCl/9Lv97GMw4E9nCTsgXqND6FMI7UqdgywpAo2hJSyE7N4vieulSJWJd5GaW/ubILwAM

将配置的公钥私钥加载到bean中,如下:

 @Autowiredprivate JwkKeyProperties jwkKeyProperties;@Beanpublic JWKSource<SecurityContext> jwkSource() {RSAKey rsaKey = new RSAKey.Builder(jwkKeyProperties.rsaPublicKey()).privateKey(jwkKeyProperties.privateKey()).build();JWKSet jwkSet = new JWKSet(rsaKey);return new ImmutableJWKSet<>(jwkSet);}

至此,授权服务器固定好公钥私钥后,我们将这些公钥、私钥用到资源服务器,如下:

# JWK 配置
cloud:jwk:rsa:# 公钥public-key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzt2qx7HwpblnbwtRV9ZiaXwvUO4JlOYYVFEDmINxp5d+Nbih8hmOrlM+4qhr5Ej1Gc+D+TJ2oNoN/wtUaGP38Kf21UhiEbRedRfdQvOEuDXmScLUBd4tJ9dH4+i5XFSnkZi3L0rlTmPLpv8SuJSnNg/POjxmBxBAnJq4qmm2c7bXqcXOa8oAQYMtBHtuA6hhbbD2tpZEr4tM010eDPrZysFeVKNFlNV9fgBL5H2s7GRqVslHEmU6vQfQGCXL2Z+jDv8WH3k3kneV7EL24IipMDjmPzxk5zw6L8uzKxANuLVnh3mCDkqnaPMN4TBTSqE5muKR5SHyGF0/dqxodmanWwIDAQAB# 私钥private-key: MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDO3arHsfCluWdvC1FX1mJpfC9Q7gmU5hhUUQOYg3Gnl341uKHyGY6uUz7iqGvkSPUZz4P5Mnag2g3/C1RoY/fwp/bVSGIRtF51F91C84S4NeZJwtQF3i0n10fj6LlcVKeRmLcvSuVOY8um/xK4lKc2D886PGYHEECcmriqabZzttepxc5rygBBgy0Ee24DqGFtsPa2lkSvi0zTXR4M+tnKwV5Uo0WU1X1+AEvkfazsZGpWyUcSZTq9B9AYJcvZn6MO/xYfeTeSd5XsQvbgiKkwOOY/PGTnPDovy7MrEA24tWeHeYIOSqdo8w3hMFNKoTma4pHlIfIYXT92rGh2ZqdbAgMBAAECggEAHBX2GbO70lGdofLIQfk466JxLXc2tNEX94aiStgkcQESoR+RWTSFbdSejUPEQOkeNzljQnef/znBEbdg5+VpZHKhgsFCPgNzmZ6Pq1yIUJb8zldAgGVy/bLvBJn0ZKftB57+K/0VV0hu/hwpLLH+ESB3Xaw/8UXlx9KtL3Hifst94yMNh2+g1qHK7BIBxVlZmm8y137lt/ZJCCKf7zDOBFFmm/Hy71K7C6uOGmRmJ7Thq7f2dJx8iecPvMv7Bzd+LzvuZdJjowZkzMXPv85hUEpbToEQUHt4FReWWk87OUSRaXUZVONZvzUHMrYqN84tvONSa+swnxGWvjK2rRcSdQKBgQDyFeqQGPzJQY2u0rhMuj12yDTssSV7xagw88KYkaWpireuSEjxJpIEhRxjO3Ow0TYvZM9t7g/6gvuYh30/FIND4AwAuRtjAjKzXfOlIG7dJMBEk5yY1tloGwxak8sa8z+H+jw9cJik+X5j6MULNzUb709UPgMstxEVrCfhgEal/QKBgQDawYXIq1q43qIuFdjFOnZ6qBHtqWtIi8lZcOSUtPuqivIVSJt7AnkNhR9MfhkgaEuoL55wBR0BA+DoZWFmObgi5Y+Udb2+nlZVufY/ksNyZ1i+4ITKhzns7qjG2W0KMh7MG0biNbTtBy54WQp+Myog1UbuXMqyMSIunwRhOC5WNwKBgQDaDK+IN1mJlUgezaI/SgkOsmopP645e+Fwpj8C2T1UJqQnkOhSfaFL/PGC2AvumaKqsay8oY823z/rNS604K8TNfzZseFfHp24Pcm1VC9HdVDQ8/w7FlogkSxhcXmhvrPcsKIN3RtAjZEwQHsrDQEDNlxHzsthPUtgL/6D+NypqQKBgQDWN2Y8ENkBajrk6E3jLZHyIP2Vfy9o1kJxTKT6npRH+FKB1x0yg0Rpoe/5Zw5R9vAHncIILmmtoc+vo/+SLHmN6sEEf5w0uzcOMdHbhWvRbzSvjotbDLsDst4iA67MqjIQa7GpOTCYYEz4WzF0TcQ2bMRODR4NCyJPBzcxwONXVwKBgH8iJJtdmftjFqOkqNLT6XzLdPE4grkSzd2/RGiK003L3n0CxE2UqzNW/oSikAO5Jc/Tsxv6FtL9o/0Kjhut05C96Ku1oJfm7QI9ORSgCl/9Lv97GMw4E9nCTsgXqND6FMI7UqdgywpAo2hJSyE7N4vieulSJWJd5GaW/ubILwAM

接下来是资源服务器的过滤器链配置:

@EnableGlobalMethodSecurity(prePostEnabled=true)
@EnableWebSecurity
@Configuration
public class ResourceServerConfig {//	@Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")String issuerUri;@Autowiredprivate JwkKeyProperties jwkKeyProperties;@BeanSecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests((authorize) -> authorize// SecurityConstant.IGNORE_PERM_URLS 不需要权限认证.requestMatchers(RedisOAuth2Constant.IGNORE_PERM_URLS).permitAll()// 其他的需要权限认证.anyRequest().authenticated())// 资源服务配置秘钥.oauth2ResourceServer().jwt(oauth2ResourceServer -> {RSAPublicKey rsaPublicKey = jwkKeyProperties.rsaPublicKey();NimbusJwtDecoder.PublicKeyJwtDecoderBuilder publicKeyJwtDecoderBuilder = NimbusJwtDecoder.withPublicKey(rsaPublicKey);NimbusJwtDecoder nimbusJwtDecoder = publicKeyJwtDecoderBuilder.build();oauth2ResourceServer.decoder(nimbusJwtDecoder);// 解析jwtoauth2ResourceServer.jwtAuthenticationConverter(getJwtToUserAuthenticationConverter());});return http.build();}public JwtToUserAuthenticationConverter getJwtToUserAuthenticationConverter(){return new JwtToUserAuthenticationConverter();}}

每次请求资源服务器的时候,手动根据公钥解析、转行jwt。这时候需要实现 Converter 接口,实现如下:

@Slf4j
//@Component
public class JwtToUserAuthenticationConverter implements Converter<Jwt, UsernamePasswordAuthenticationToken> {@Overridepublic UsernamePasswordAuthenticationToken convert(@NotNull Jwt jwt) {System.out.println("------"+ JSON.toJSONString(jwt));/*** 方案一:从 jwt 中的 claims - >authorities 获取权限信息* 方案二: 根据 jwt.getSubject() 登录名去查数据库对应的用户权限*/CustomUserDetails details =  new CustomUserDetails();// todo 调用用户接口String subject = jwt.getSubject();log.info("从jwt获取的用户名:{}",subject);details.setUsername(subject);/*** hasRole  对应的是 ROLE_admin* hasAuthority 对应的是 user:list** 在做权限的时候需要注意 security 权限前缀*/details.setRoles(List.of("admin","user:list","user"));return new UsernamePasswordAuthenticationToken(details, jwt, details.getAuthorities());}}

至此,资源服务器的授权操作及jwt的解析完成。

3、结论

不管根据哪种方案实现,其实都需要了解授权过程。也就是授权(token中存放用户名、授权信息),接着资源服务器的token处理过程,可以直接请求授权服务器,由授权服务器验证;也可以在授权服务器确定固定的公钥私钥,资源服务器自己根据公钥解析token,获取jwt,最后获取用户信息。

以上的源码来源自己开源项目:

oauth2-resource资源服务器

oauth2-server 授权服务器


http://www.ppmy.cn/news/1038381.html

相关文章

shell脚本之函数及数组

shell脚本之函数及数组 一函数1.1函数的作用1.2函数的基本格式1.3函数的注意事项1.4函数调用的方法1.5函数的返回值1.6函数的传参1.7在外部调用函数1.8函数变量的作用范围1.9函数的递归 二.数组2.1shell数组的定义2.2定义属组的方式2.3数组的数据类型2.4获取数组的数据列表2.5获…

【100天精通python】Day38:GUI界面编程_PyQT从入门到实战(中)

目录 专栏导读 4 数据库操作 4.1 连接数据库 4.2 执行 SQL 查询和更新&#xff1a; 4.3 使用模型和视图显示数据 5 多线程编程 5.1 多线程编程的概念和优势 5.2 在 PyQt 中使用多线程 5.3 处理多线程间的同步和通信问题 5.3.1 信号槽机制 5.3.2 线程安全的数据访问 Q…

稳如磐石!亿级别MySQL大表迁移的解密

MySQL 作为当前应用最广泛的开源关系型数据库之一&#xff0c;具有高性能、稳定性和易用性等特性&#xff0c;是许多网站、应用和商业产品的主要数据存储。在一些场景中&#xff0c;如果出现单表行数上亿的情况&#xff0c;就可能需要开发和 DBA 对大表进行优化&#xff1a;分表…

【Ubuntu】简洁高效企业级日志平台后起之秀Graylog

简介 Graylog 是一个用于集中式日志管理的开源平台。在现代数据驱动的环境中&#xff0c;我们需要处理来自各种设备、应用程序和操作系统的大量数据。Graylog提供了一种方法来聚合、组织和理解所有这些数据。它的核心功能包括流式标记、实时搜索、仪表板可视化、告警触发、内容…

华为OD机试真题【字母组合】

1、题目描述 【字母组合】 数字0、1、2、3、4、5、6、7、8、9分别关联 a~z 26个英文字母。 0 关联 “a”,”b”,”c” 1 关联 “d”,”e”,”f” 2 关联 “g”,”h”,”i” 3 关联 “j”,”k”,”l” 4 关联 “m”,”n”,”o” 5 关联 “p”,”q”,”r” 6 关联 “s”,”t” 7…

搭建Web服务器并用cpolar发布至公网访问

本地电脑搭建Web服务器并用cpolar发布至公网访问 文章目录 本地电脑搭建Web服务器并用cpolar发布至公网访问前言1. 首先在电脑安装PHPStudy、WordPress、cpolar2. 安装cpolar&#xff0c;进入Web-UI界面3. 安装wordpress4. 进入wordpress网页安装程序5. 利用cpolar建立的内网穿…

Arcgis连续数据的分类(求不同值域的面积)

问题描述&#xff1a;如果得到的一个连续的影响数值数据&#xff0c;但是我们想求取某一段值域的面积占比&#xff0c;需要进行以下操作&#xff1a; 1.按照数值重分类&#xff0c;将某段数值变成一个类别 2.栅格转矢量&#xff0c;再求取面积

Socks5代理在多线程爬虫中的应用

在进行爬虫开发过程中&#xff0c;我们常常需要处理大量的数据&#xff0c;并执行多任务并发操作。然而&#xff0c;频繁的请求可能会引起目标网站的反爬机制&#xff0c;导致IP封禁或限制访问。为了规避这些限制&#xff0c;我们可以借助Socks5代理的强大功能&#xff0c;通过…