002-从零搭建微服务-认证中心(二)

2023-10-27

写在最前

如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。

源码地址:https://gitee.com/csps/mingyue

文档地址:https://gitee.com/csps/mingyue/wikis

创建新项目 MingYue

Idea 创建 maven 项目这儿就不多赘述了,相信各位大佬都是信手拈来~

MingYue Pom

父项目的依赖都放在这儿了,后续用到什么再增加什么

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.csp.mingyue</groupId>
    <artifactId>mingyue</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>

    <name>MingYue</name>
    <description>MingYue 微服务系统</description>

    <properties>
        <mingyue.version>1.0.0</mingyue.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <java.version>1.8</java.version>

        <!-- Spring 版本 -->
        <spring-boot.version>2.7.11</spring-boot.version>
        <spring-cloud.version>2021.0.6</spring-cloud.version>
        <spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>

        <!-- 工具版本 -->
        <jasypt.version>3.0.5</jasypt.version>
        <hutool.version>5.8.18</hutool.version>
        <lombok.version>1.18.26</lombok.version>
        <spring.checkstyle.plugin>0.0.38</spring.checkstyle.plugin>
    </properties>

    <!-- 以下依赖 全局所有的模块都会引入  -->
    <dependencies>
        <!--配置文件处理器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <!--配置文件加解密-->
        <dependency>
            <groupId>com.github.ulisesbocchio</groupId>
            <artifactId>jasypt-spring-boot-starter</artifactId>
            <version>${jasypt.version}</version>
        </dependency>
        <!--Lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
        <!--测试依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!-- 依赖声明 -->
    <dependencyManagement>
        <dependencies>
            <!-- spring boot 依赖 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- spring cloud 依赖 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- spring cloud alibaba 依赖 -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- hutool 的依赖配置-->
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-bom</artifactId>
                <version>${hutool.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

创建子项目 MingYue-Auth

Idea mingyue 右击 -> New -> Module

image-20230526103113168

核心依赖

<properties>
        <sa-token.version>1.34.0</sa-token.version>
</properties>

<dependencies>
  <!-- SpringBoot依赖 -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <!-- Sa-Token 权限认证, 在线文档:https://sa-token.cc/ -->
  <dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot-starter</artifactId>
    <version>${sa-token.version}</version>
  </dependency>

  <!-- Sa-Token-OAuth2.0 模块 -->
  <dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-oauth2</artifactId>
    <version>${sa-token.version}</version>
  </dependency>

  <!-- Sa-Token 整合redis (使用jackson序列化方式) -->
  <dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-dao-redis-jackson</artifactId>
    <version>${sa-token.version}</version>
  </dependency>

  <!-- 提供Redis连接池 -->
  <dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
  </dependency>

  <!-- 视图引擎(在前后端不分离模式下提供视图支持) -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
  </dependency>
</dependencies>

SaOAuth2ServerController

/**
 * Sa-OAuth2 Server端 控制器
 * @author kong
 *
 */
@RestController
public class SaOAuth2ServerController {

	// 处理所有OAuth相关请求
	@RequestMapping("/oauth2/*")
	public Object request() {
		System.out.println("------- 进入请求: " + SaHolder.getRequest().getUrl());
		return SaOAuth2Handle.serverRequest();
	}

	// Sa-OAuth2 定制化配置
	@Autowired
	public void setSaOAuth2Config(SaOAuth2Config cfg) {
		cfg.
			// 未登录的视图
			setNotLoginView(()->{
				return new ModelAndView("login.html");
			}).
			// 登录处理函数
			setDoLoginHandle((name, pwd) -> {
				if("sa".equals(name) && "123456".equals(pwd)) {
					StpUtil.login(10001);
					return SaResult.ok();
				}
				return SaResult.error("账号名或密码错误");
			}).
			// 授权确认视图
			setConfirmView((clientId, scope)->{
				Map<String, Object> map = new HashMap<>();
				map.put("clientId", clientId);
				map.put("scope", scope);
				return new ModelAndView("confirm.html", map);
			})
			;
	}

	// 全局异常拦截
	@ExceptionHandler
	public SaResult handlerException(Exception e) {
		e.printStackTrace();
		return SaResult.error(e.getMessage());
	}


	// ---------- 开放相关资源接口: Client端根据 Access-Token ,置换相关资源 ------------

	// 获取Userinfo信息:昵称、头像、性别等等
	@RequestMapping("/oauth2/userinfo")
	public SaResult userinfo() {
		// 获取 Access-Token 对应的账号id
		String accessToken = SaHolder.getRequest().getParamNotNull("access_token");
		Object loginId = SaOAuth2Util.getLoginIdByAccessToken(accessToken);
		System.out.println("-------- 此Access-Token对应的账号id: " + loginId);

		// 校验 Access-Token 是否具有权限: userinfo
		SaOAuth2Util.checkScope(accessToken, "userinfo");

		// 模拟账号信息 (真实环境需要查询数据库获取信息)
		Map<String, Object> map = new LinkedHashMap<String, Object>();
		map.put("nickname", "shengzhang_");
		map.put("avatar", "http://xxx.com/1.jpg");
		map.put("age", "18");
		map.put("sex", "男");
		map.put("address", "山东省 青岛市 城阳区");
		return SaResult.data(map);
	}

}

SaOAuth2TemplateImpl

/**
 * Sa-Token OAuth2.0 整合实现
 * @author kong
 */
@Component
public class SaOAuth2TemplateImpl extends SaOAuth2Template {

	// 根据 id 获取 Client 信息
	@Override
	public SaClientModel getClientModel(String clientId) {
		// 此为模拟数据,真实环境需要从数据库查询
		if("1001".equals(clientId)) {
			return new SaClientModel()
					.setClientId("1001")
					.setClientSecret("aaaa-bbbb-cccc-dddd-eeee")
					.setAllowUrl("*")
					.setContractScope("userinfo")
					.setIsAutoMode(true);
		}
		return null;
	}

	// 根据ClientId 和 LoginId 获取openid
	@Override
	public String getOpenid(String clientId, Object loginId) {
		// 此为模拟数据,真实环境需要从数据库查询
		return "gr_SwoIN0MC1ewxHX_vfCW3BothWDZMMtx__";
	}
}

添加 templates

  • confirm.html
  • login.html

创建启动类启动项目

@SpringBootApplication
public class MingYueAuthApplication {

	public static void main(String[] args) {
		SpringApplication.run(MingYueAuthApplication.class, args);
		System.out.println("\nSa-Token-OAuth  Server端启动成功: http://localhost:9000/oauth2/authorize?response_type=code&client_id=1001&redirect_uri=https://sa-token.cc&scope=userinfo");
	}

}

启动项目,访问打印地址:

Sa-Token-OAuth Server端启动成功: http://localhost:9000/oauth2/authorize?response_type=code&client_id=1001&redirect_uri=https://sa-token.cc&scope=userinfo

API 列表

共四种模式,分别是授权码(Authorization Code)隐藏式(Implicit)密码式(Password)凭证式(Client Credentials),本文介绍了两种常用的:授权码(Authorization Code)、密码式(Password)

1. 授权码(Authorization Code)

http://localhost:9000/oauth2/authorize
?response_type=code
&client_id=1001
&redirect_uri=https://sa-token.cc&scope=userinfo

参数详解:

参数 是否必填 说明
response_type 返回类型,这里请填写:code
client_id 应用id
redirect_uri 用户确认授权后,重定向的url地址
scope 具体请求的权限,多个用逗号隔开
state 随机值,此参数会在重定向时追加到url末尾,不填不追加
1.1 获取授权码

Code授权码具有以下特点:

  1. 每次授权产生的 Code 码都不一样
  2. Code码用完即废,不能二次使用
  3. 一个Code的有效期默认为五分钟,超时自动作废
  4. 每次授权产生新 Code 码,会导致旧 Code 码立即作废,即使旧 Code 码尚未使用

http://localhost:9000/oauth2/authorize?response_type=code&client_id=1001&redirect_uri=https://sa-token.cc&scope=userinfo

打开地址,登录并同意授权

image-20230525195925531

地址栏拿到 code https://sa-token.cc/?code=ct0RB10UkGSwXINdBkGRGVKBvoKjIi6jzeYi3NFrCwoXzDr36Ljgm1ZBplYx

1.2 根据授权码获取 Access-Token

浏览器直接访问:

http://localhost:9000/oauth2/token
    ?grant_type=authorization_code
    &client_id=1001
    &client_secret=aaaa-bbbb-cccc-dddd-eeee
    &code=ktN6FvIfB7pKqp7Thvkm32EfUhbveoybwOtmvqCCbuLdxevmyr9FW09Kd6qL
参数 是否必填 说明
grant_type 授权类型,这里请填写:authorization_code
client_id 应用id
client_secret 应用秘钥
code 步骤1.1中获取到的授权码

打印如下:

{
    "code": 200,
    "msg": "ok",
    "data": {
        "access_token": "E1ZLgNXLiUIz8DmAxmgPeegMPsUCEJJLjUV9uwDQWCu4f6Tgg8U5JqKSrqSx",
        "refresh_token": "0IAWolcbMvoIpF8F1JcEuytfcoTe8nNVwsEdUHOy7rBX0V99vhPBvtFGfh62",
        "expires_in": 7199,
        "refresh_expires_in": 2591999,
        "client_id": "1001",
        "scope": "userinfo",
        "openid": "gr_SwoIN0MC1ewxHX_vfCW3BothWDZMMtx__"
    }
}

2. 密码式(Password)

首先在 Client 端构建表单,让用户输入 Server 端的账号和密码,然后在 Client 端访问接口

http://localhost:9000/oauth2/token
    ?grant_type=password
    &client_id=1001
    &client_secret=aaaa-bbbb-cccc-dddd-eeee
    &username=sa
    &password=123456
参数 是否必填 说明
grant_type 返回类型,这里请填写:password
client_id 应用id
client_secret 应用秘钥
username 用户的Server端账号
password 用户的Server端密码
scope 具体请求的权限,多个用逗号隔开

浏览器直接访问,打印如下:

{
    "code": 200,
    "msg": "ok",
    "data": {
        "access_token": "BvU1yja6sy4WT3orCvIiYExIOhGMBwVps38ZywZWGaeYaM6nJbPkJRbHpmSC",
        "refresh_token": "TzSGmGhtPuAZUZ5ndfVETdmmpGr3ZwAH5N5kbrEYeeR2LKbLBXEysqsLxuV6",
        "expires_in": 7199,
        "refresh_expires_in": 2591999,
        "client_id": "1001",
        "scope": "",
        "openid": "gr_SwoIN0MC1ewxHX_vfCW3BothWDZMMtx__"
    }
}

至此,一个基于 OAuth2 的认证中心 Demo 就完成啦,接下来我们先优化一下代码结构。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

002-从零搭建微服务-认证中心(二) 的相关文章

随机推荐

  • cmd如何返回上一级目录,如何进入其他文件目录

    当我们打开cmd或者composer运行命令时都会进入一个默认文件目录 那么cmd该如何返回上一级目录 和如何进入其他文件目录运行命令呢 具体方法如下图所示 1 在默认的命令后加 cd 即可返回上一级目录 2 cmd进入其他文件目录 2 1
  • 基于.net平台常用的框架整理

    分布式缓存框架 Microsoft Velocity 微软自家分布式缓存服务框架 Memcahed 一套分布式的高速缓存系统 目前被许多网站使用以提升网站的访问速度 Redis 是一个高性能的KV数据库 它的出现很大程度补偿了Memcach
  • 若依后台管理系统学习

    前端系统是指运行在浏览器或者移动设备上的用户界面层 它负责与用户交互 展示数据 调用后端服务等 前端系统的架构设计需要考虑以下几个方面 前端系统在整个系统中的位置和关系 你需要明确前端系统与后端服务 数据库 第三方接口等的架构上的关系 业务
  • requests模块----这是一个强硬的手段,有多强呢?看看你就知道了

    目录 requests的作 发送简单的get请求 发送带header的请求 发送POST请求 cookies参数的使 cookie和session区别 使 代理 设置请求超时时间 请求SSL证书 开始了 requests模块简单介绍 1 r
  • Java8基础之Serializable接口

    Serializable接口介绍 Serializable 是 java io 包中定义的 用于实现 Java 类的序列化操作而提供的一个语义级别的接口 Serializable 序列化接口没有任何方法或者字段 只是用于标识可序列化的语义
  • shift算法的实现

    ok 接上文 咱们一个一个的来编写main函数中所涉及到所有函数 这也是本文的关键部分 cpp view plain copy print 下采样原来的图像 返回缩小2倍尺寸的图像 CvMat halfSizeImage CvMat im
  • ***总结:在linux下连接redis并进行命令行操作(设置redis密码)

    root iZ254lfyd6nZ cd root iZ254lfyd6nZ ls bin boot dev etc home lib lib64 lost found media mnt opt proc root sbin selinu
  • 通信算法之184: 物理层DPD/CFR/LNA/PA

  • 机器人教育在STEM课程中的设计研究

    在美国 科学 技术 工程和数学 STEM 教育被视为确保国家成功未来的重要一步 基于现实世界中的问题开发的STEM课程 可以使课程更贴近学生和教师 对于更优质的STEM教育的迫切要求主要基于以下因素的考虑 许多职业现在需要一支能够参与STE
  • 啊哈C——学习6.4陶陶摘苹果

    2015年2月5日22 02 03 1 陶陶家的院子里有一颗苹果树 每到秋天树上就会结出10个苹果 苹果成熟的时候 陶陶就会跑去摘苹果 陶陶有个30cm高的板凳 当她不能直接用手摘到苹果是 就会踩到板凳上再试试 现在一直10个苹果到地面的高
  • 华为OD机试 -百钱买百鸡问题(C++ & Java & JS & Python)

    描述 公元五世纪 我国古代数学家张丘建在 算经 一书中提出了 百鸡问题 鸡翁一值钱五 鸡母一值钱三 鸡雏三值钱一 百钱买百鸡 问鸡翁 鸡母 鸡雏各几何 现要求你打印出所有花一百元买一百只鸡的方式 输入描述 输入任何一个整数 即可运行程序 输
  • 树莓派4b配置OpenWrt联网

    文章目录 前言 一 下载固件 二 配置wan口 三 简单介绍 1 修改无线名称 设置密码 2 下载软件包 总结 前言 树莓派4b内置wifi模块 加一个千兆网口 好像有一种办法 通过无线wifi链接其他wifi通网 然后把这个网口作为lan
  • 登录鉴权

    注册登录鉴权 1 1 用户注册 前台需要给我们传递用户名 密码 手机号 手机验证码 验证用户前台传过来的数据是否符合规范 我们使用的Hibernate Validator框架实现的服务端表单校验 短信验证码这块 我们采用的阿里的大于短信接口
  • python 处理数据小工具_Python数据处理工具使用方法整理

    从csv文件创建DataFrame类型的数据结构 gt gt gt df pd read csv xxx csv DataFrame类型的形状和长度 gt gt gt df shape 38 39 gt gt gt len df 38 各列
  • mac的Vscode 中 Remote-SSH 连接不上服务器,但是在终端中使用SSH可以连接

    Vscode 中 Remote SSH 连接不上服务器 但是在终端中使用SSH可以连接 我试了各种办法 最后准备删除配置文件看看 结果发现没有权限 怀疑是我用了conda管理环境 可能造成base环境权限变了 总之 我在vscode的终端中
  • 解决android每次请求,后台sessionId都会变换(springboot配置web.xml)

    问题 后台生成验证码以后 存放到session缓存中 将验证码发送给指定手机 当安卓手机输入验证码调用注册接口时候 后台接口从session中无法取出放入的验证码 原因 android每次请求 后台sessionId都会变换 解决方法 1
  • Word论文书写--页眉线设置

    开始 gt 段落 gt 边框和底纹 基本设置如下 结果
  • 用Flex布局模型开发网页

    目录 一 为什么要用Flex布局 对比浮动有什么优点 二 Flex布局组成 三 如何使用Flex布局 1 基本方法 2 主轴对齐方式 3 侧轴对齐 4 改变主轴方向 5 弹性盒子换行 四 弹性盒子多场景运用 1 圣杯布局 2 如何让父盒子里
  • JBoss 系列四十四:jBPM5示例之 GateWay

    jBPM5中的GateWay如果选择AND则表示平行执行多个Task ParallelExecute示例演示jBPM5中如何平行执行多个Task ParallelExecute流程如下 上图为平行执行多个Task的流程 其中Task1 1
  • 002-从零搭建微服务-认证中心(二)

    写在最前 如果这个项目让你有所收获 记得 Star 关注哦 这对我是非常不错的鼓励与支持 源码地址 https gitee com csps mingyue 文档地址 https gitee com csps mingyue wikis 创