04_学习springdoc与oauth结合_简述

文章目录

  • 1 前言
  • 2 基本结构
  • 3 需要做的配置 简述
  • 4 需要做的配置 详述
    • 4.1 backend-api-gateway 的配置
      • 4.1.1 application.yml
    • 4.2 backend-film 的配置
      • 4.2.1 pom.xml 引入依赖
      • 4.2.2 application.yml 的配置
      • 4.2.3 Spring Security 资源服务器的配置类 MyResourceServerConfig
      • 4.2.4 Springdoc 配置类 MySpringdocConfig
    • 4.3 backend-cinema 的配置
      • 4.3.1 Feign JWT 中继的拦截器
    • 4.4 auth-gateway 的配置
      • 4.4.1 application.yml
    • 4.5 auth-server 的配置
      • 4.5.1 向数据库表 oauth2_registered_client 添加 client 信息
  • 5 最后差点忘了😂 API 接口的 swagger 注解也需要修改
  • 6 结语

1 前言

  在上一篇文章 《03_学习springdoc与微服务结合_简述》 的基础上,我们可以更进一步,把 认证授权中心 Spring Authorization Server 也拽进来,让事情变得更复杂一些。😂也许事情总是会从简单到复杂。

  本文的代码,是基于 Spring Boot 3.1.3、Spring Cloud 2022.0.4、Java 17 构建的。

2 基本结构

  基本的组成部分 图示:

在这里插入图片描述

  springdoc swagger ui 使用 oauth 认证和授权的流程,时序图:

在这里插入图片描述

3 需要做的配置 简述

  如下图,一共有 5 块儿地方(红字所示),需要做配置:

在这里插入图片描述

  简单说明一下,因为上一篇文章《03_学习springdoc与微服务结合_简述》已经对上图左侧 电影APP后台系统,做了 springdoc 与各个服务的整合,所以现在只剩下它们与 oauth2 的整合,以及 JWT 在 feign 的中继。

  上图右侧的认证授权中心,是基于 spring-boot-starter-oauth2-authorization-server 写的,至于它如何配置,可以参考 Spring 官网 https://spring.io/projects/spring-authorization-server ,这里不再赘述。配置好之后,我们就只需要向数据库表添加 client 信息了。

  注意,127.0.0.1 和 192.168.0.111 其实都是我本机 localhost,但是因为 eureka-server 和 spring authorization server 的缘故(🤣我也不知道具体什么原因),如果都用 127.0.0.1 ,则 spring authorization server 的反应会不正常。

4 需要做的配置 详述

  有了上面的简述,接下来我们按照图片,把需要做的配置,一个个详细地说明。

4.1 backend-api-gateway 的配置

4.1.1 application.yml

springdoc:swagger-ui:urls:- name: backend-cinemaurl: /cateye/backend-cinema/v3/api-docs- name: backend-filmurl: /cateye/backend-film/v3/api-docs# 重点是下面这一句# 指定 swagger oauth2 授权码流程的 redirectUrl , 默认是 /swagger-ui/oauth2-redirect.html# 这里选择了 backend-film 服务的 swagger redirectUrl# 其实选择 backend-cinema 的也可以. 随便指定一个能访问的就行oauth2-redirect-url: http://127.0.0.1:8080/cateye/backend-film/swagger-ui/oauth2-redirect.htmlcache:disabled: true

4.2 backend-film 的配置

4.2.1 pom.xml 引入依赖

<!-- oauth 资源服务 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>

4.2.2 application.yml 的配置

spring:application:name: backend-filmsecurity:oauth2:# 授权服务器的 URLresourceserver:jwt:# 这个是 auth-gateway. 在 auth-server 里面,我设置的 issuer-uri 也是直接访问网关issuer-uri: http://192.168.0.111:9090# springdoc 的配置
springdoc:swagger-ui:oauth:# oauth 客户端的 clientId 和 clientSecretclientId: cat-eye-background-backend-film-swaggerclientSecret: passwordcache:disabled: true# 授权码流程的2个urloAuthFlow:authorizationUrl: ${spring.security.oauth2.resourceserver.jwt.issuer-uri}/oauth2/authorizetokenUrl: ${spring.security.oauth2.resourceserver.jwt.issuer-uri}/oauth2/token

4.2.3 Spring Security 资源服务器的配置类 MyResourceServerConfig

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;@EnableWebSecurity
@Configuration
public class MyResourceServerConfig {/*** 资源服务器的 spring security 过滤器链*/@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(authorize -> authorize// 放行 swagger 相关的页面.requestMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll()// 演员相关的权限控制.requestMatchers("/actor/search-by-id/**","/actor/search-page").hasAuthority("SCOPE_actor.read").requestMatchers("/actor/**").hasAuthority("SCOPE_actor.write")// 影片相关的权限控制.requestMatchers("/film/search-by-id/**","/film/search-page","/film/search-batch").hasAuthority("SCOPE_film.read").requestMatchers("/film/**").hasAuthority("SCOPE_film.write")// 剩余的都至少需要认证.anyRequest().authenticated()).oauth2ResourceServer((oauth2) -> oauth2.jwt(Customizer.withDefaults()));return http.build();}
}

4.2.4 Springdoc 配置类 MySpringdocConfig

  😂因为要配置的挺多,我们就使用注解形式的配置吧,写起来简洁明了一些。下面配置的是 OAuth2 的授权码流程。

import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.info.License;
import io.swagger.v3.oas.annotations.security.*;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.security.Scopes;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@OpenAPIDefinition(info = @Info(title = "电影APP后台-影片模块 API", version = "1.0.0", description = "包含了影片和演员相关的 API",license = @License(name = "Apache 2.0", url = "https://www.apache.org/licenses/LICENSE-2.0")))
@SecurityScheme(name = "security_auth", type = SecuritySchemeType.OAUTH2,flows = @OAuthFlows(authorizationCode = @OAuthFlow(authorizationUrl = "${springdoc.oAuthFlow.authorizationUrl}",tokenUrl = "${springdoc.oAuthFlow.tokenUrl}",scopes = {@OAuthScope(name = "actor.read", description = "演员读权限"),@OAuthScope(name = "actor.write", description = "演员写权限"),@OAuthScope(name = "film.read", description = "影片读权限"),@OAuthScope(name = "film.write", description = "影片写权限")})))
@Configuration
public class MySpringdocConfig {
}

  效果如下图:

在这里插入图片描述

4.3 backend-cinema 的配置

4.3.1 Feign JWT 中继的拦截器

  本文参考自 《JWT如何在OpenFeign调用中进行令牌中继》https://juejin.cn/post/7023246872147918885 ,把用到的代码拷贝如下:

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;@Component
public class FeignBearerTokenRequestInterceptor implements RequestInterceptor {private static final Pattern BEARER_TOKEN_HEADER_PATTERN = Pattern.compile("^Bearer (?<token>[a-zA-Z0-9-._~+/]+=*)$",Pattern.CASE_INSENSITIVE);@Overridepublic void apply(RequestTemplate template) {final String authorization = HttpHeaders.AUTHORIZATION;ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();if (Objects.nonNull(requestAttributes)) {String authorizationHeader = requestAttributes.getRequest().getHeader(HttpHeaders.AUTHORIZATION);Matcher matcher = BEARER_TOKEN_HEADER_PATTERN.matcher(authorizationHeader);if (matcher.matches()) {// 清除token头 避免传染template.header(authorization);template.header(authorization, authorizationHeader);}}}
}

4.4 auth-gateway 的配置

4.4.1 application.yml

spring:application:name: auth-gatewaycloud:gateway:# CORS配置globalcors:cors-configurations:'[/**]':allowedOrigins: "*"allowedMethods:- GET- HEAD- POST- PUT- DELETE- TRACE- OPTIONS- PATCHallowedHeaders: "*"

4.5 auth-server 的配置

4.5.1 向数据库表 oauth2_registered_client 添加 client 信息

  如下图:

在这里插入图片描述

可以在 auth-server 的 test 类里面,通过代码 insert 一行 client 信息,如下:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mariadb.jdbc.MariaDbDataSource;
import org.springframework.jdbc.core.JdbcTemplate;
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.server.authorization.client.JdbcRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;import java.sql.SQLException;
import java.util.UUID;public class SecurityTest {@Testpublic void addRegisteredClient() throws SQLException {MariaDbDataSource dataSource = new MariaDbDataSource();dataSource.setUrl("jdbc:mariadb://192.168.56.1:3306/cateye?autoReconnect=true&allowMultiQueries=true");dataSource.setUser("sjzadmin");dataSource.setPassword("P_sjz123");JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);JdbcRegisteredClientRepository repository = new JdbcRegisteredClientRepository(jdbcTemplate);RegisteredClient client = RegisteredClient.withId(UUID.randomUUID().toString()).clientId("cat-eye-background-backend-cinema-swagger")// 注意 密码不能重复, 所以可以稍稍修改下密码, 然后再直接 SQL 改回来.clientSecret("1$2a$10$To/16R/ZmbYlSqvpb9G2OOwZPrGO7VC52WLQUPtVMciymzujN/s4i")// 注意 swagger 的 client_id client_secret 是通过 POST 请求的请求体过来的// 而不是在 HTTP Basic 里面, 所以下面要用 CLIENT_SECRET_POST.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST).authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN).authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).redirectUri("http://127.0.0.1:8080/cateye/backend-film/swagger-ui/oauth2-redirect.html").scope(OidcScopes.OPENID).scope(OidcScopes.PROFILE).scope("movie.hall.read").scope("movie.hall.write").scope("film.read").build();repository.save(client);RegisteredClient dbClient = repository.findByClientId("cat-eye-background-backend-cinema-swagger");Assertions.assertNotNull(dbClient);}
}

5 最后差点忘了😂 API 接口的 swagger 注解也需要修改

@Tag(name = "02_影片", description = "影片 API")
@ApiResponses(@ApiResponse(responseCode = "200", description = "接口请求成功"))
public interface FilmApi {// 注意,接口的 Operation 注解里面要加 security 属性// 其 name 就是 4.2.4 小节 MySpringdocConfig 类里面定义的// @SecurityScheme(name = "security_auth")@Operation(summary = "分页查询影片", security = @SecurityRequirement(name = "security_auth"))@RequestMapping(value = "/film/search-page", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)JsonResult<PageInfo<FilmBriefResp>> searchPage(@Valid @RequestBody PageReq<FilmSearchPageReq> pageReq);
}

6 结语

  因本文涉及的代码是学习用的小项目中的代码,而生产环境可能更加复杂吧,所以本文仅供参考😁

  感谢阅读~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/101877.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue打印功能

安装 vue3-print-nb yarn add vue3-print-nb //或 npm install vue3-print-nbmain.js中引入 vue3-print-nb import { createApp } from vue; import App from ./App.vue; const app createApp(App); // 打印插件 import print from vue3-print-nb app.use(print) //页面内引…

Webapck 解决:[webpack-cli] Error: Cannot find module ‘vue-loader/lib/plugin‘ 的问题

1、问题描述&#xff1a; 其一、报错为&#xff1a; [webpack-cli] Error: Cannot find module vue-loader/lib/plugin 中文为&#xff1a; [webpack-cli] 错误&#xff1a;找不到模块“vue-loader/lib/plugin” 其二、问题描述为&#xff1a; 在项目打包的时候 npm run …

c++视觉图像----扩充边界

图像扩充边界 #include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp>int main() {// 读取图像cv::Mat image cv::imread("1.jpg", cv::IMREAD_COLOR);if (image.empty()) {std::cerr << "Could not open or find the imag…

Java项目调用Python脚本(基于idea)

前期准备 1.首先需要在本地环境中安装配置python环境 Python(含PyCharm及配置)下载安装以及简单使用(Idea) 博主本次使用python版本为py3.7.3 2.idea安装python插件 位置&#xff1a;File->Settings->Plugins->python->安装后重启即可 3.引入jython依赖 &l…

力扣 -- 1312. 让字符串成为回文串的最少插入次数

解题步骤&#xff1a; 参考代码&#xff1a; class Solution { public:int minInsertions(string s) {int ns.size();vector<vector<int>> dp(n,vector<int>(n));//无需初始化//填表for(int in-1;i>0;i--){for(int ji;j<n;j){//状态转移方程if(s[i]s[…

如何在 Spring Boot 中进行数据备份

在Spring Boot中进行数据备份 数据备份是确保数据安全性和可恢复性的关键任务之一。Spring Boot提供了多种方法来执行数据备份&#xff0c;无论是定期备份数据库&#xff0c;还是将数据导出到外部存储。本文将介绍在Spring Boot应用程序中进行数据备份的不同方法。 方法1: 使用…

【深度学习实验】循环神经网络(一):循环神经网络(RNN)模型的实现与梯度裁剪

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. 数据处理 2. rnn 测试 3. grad_clipping 4. 代码整合 经验是智慧之父&#xff0c;记忆是智慧之母。 ——谚语 一、实验介绍 本实验介绍了一个简单的循环神经网络…

如何优化前端图像和多媒体资源?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

电子书制作软件Vellum mac中文版特点

Vellum mac是一款专业的电子书制作软件&#xff0c;它可以帮助用户将文本文件转换为高质量的电子书&#xff0c;支持多种格式&#xff0c;包括EPUB、MOBI、PDF等。Vellum具有直观的用户界面和易于使用的工具&#xff0c;可以让用户快速地创建和发布电子书。 Vellum mac软件特点…

与艺术同频!卡萨帝在海外崭露头角

在品牌全球化步伐日益加快的当下&#xff0c;高端品牌如何真正实现业务全球化、品牌全球化乃至用户圈层全球化&#xff1f; 作为国际高端家电引领者&#xff0c;卡萨帝今年以来在全球范围内展开了一系列的品牌布局活动。1月&#xff0c;卡萨帝于巴基斯坦召开品牌发布会&#x…

分类预测 | MATLAB实现基于RF-Adaboost随机森林结合AdaBoost多输入分类预测

分类预测 | MATLAB实现基于RF-Adaboost随机森林结合AdaBoost多输入分类预测 目录 分类预测 | MATLAB实现基于RF-Adaboost随机森林结合AdaBoost多输入分类预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.MATLAB实现基于RF-Adaboost随机森林结合AdaBoost多输…

手写Spring系列【一】IOC的简单实现笔记

前言&#xff1a; &#x1f44f;作者简介&#xff1a;我是笑霸final&#xff0c;一名热爱技术的在校学生。 &#x1f4dd;个人主页&#xff1a;个人主页1 || 笑霸final的主页2 &#x1f4d5;系列专栏&#xff1a;项目专栏 &#x1f4e7;如果文章知识点有错误的地方&#xff0c;…

大日志(大文件)查看工具

一款很不错的日志查看工具&#xff0c; 优势是能查看很大的日志文档。 无需安装&#xff0c;解压后运行即可&#xff1b; 有注册版&#xff0c;不注册也可以使用。 官方地址&#xff1a; LogViewer - Home page 一个下载地址&#xff1a; 日志查看工具UVviewsoft LogViewer(超大…

电脑如何查看是否支持虚拟化及如何开启虚拟化

什么是虚拟化? Intel Virtualization Technology就是以前众所周知的“Vanderpool”技术&#xff08;简称VT&#xff0c;中文译为虚拟化技术&#xff09;&#xff0c;这种技术可以让一个CPU工作起来就像多个CPU并行运行&#xff0c;从而使得在一部电脑内同时运行多个操作系统成…

开山之作 | YOLOv1算法超详细解析(包括诞生背景+论文解析+技术原理等)

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。目标检测是计算机视觉领域的一项重要研究方向&#xff0c;它在许多应用领域中都得到了广泛应用&#xff0c;如人脸识别、物体识别、自动驾驶、视频监控等。在过去&#xff0c;目标检测方法主要采用基于RCNN、Fast R-CNN等深…

Python+Tkinter 图形化界面基础篇:集成数据库

PythonTkinter 图形化界面基础篇&#xff1a;集成数据库 引言为什么选择 SQLite 数据库&#xff1f;集成 SQLite 数据库的步骤示例&#xff1a;创建一个任务管理应用程序步骤1&#xff1a;导入必要的模块步骤2&#xff1a;创建主窗口和数据库连接步骤3&#xff1a;创建数据库表…

高级深入--day30

Scrapy Shell Scrapy终端是一个交互终端,我们可以在未启动spider的情况下尝试及调试代码,也可以用来测试XPath或CSS表达式,查看他们的工作方式,方便我们爬取的网页中提取的数据。 如果安装了 IPython ,Scrapy终端将使用 IPython (替代标准Python终端)。 IPython 终端与其…

从零开始:深入理解Kubernetes架构及安装过程

K8s环境搭建 文章目录 K8s环境搭建集群类型安装方式环境规划克隆三台虚拟机系统环境配置集群搭建初始化集群&#xff08;仅在master节点&#xff09;配置环境变量&#xff08;仅在master节点&#xff09;工作节点加入集群&#xff08;knode1节点及knode2节点&#xff09;安装ca…

1806_emacs_org-mode归档的时候修改归档文件名称

全部学习汇总&#xff1a;GreyZhang/g_org: my learning trip for org-mode (github.com) 前面已经基本了解了org-mode的归档的规则或者方法&#xff0c;但是还有一点跟我现在的工作流有点不相符。我自己的工作流中会每月做一次工作的整理总结&#xff0c;因此归档的文件是按照…

C++ PCL点云局部颜色变换

程序示例精选 C PCL点云局部颜色变换 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《C PCL点云局部颜色变换》编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易读。 学习与应用…