Spring Authorization Server入门 (十八) Vue项目使用PKCE模式对接认证服务

Vue单页面项目使用授权码模式对接流程说明

以下流程摘抄自官网

在本例中为授权代码流程。 授权码流程的步骤如下:

  1. 客户端通过重定向到授权端点来发起 OAuth2 请求。 对于公共客户端,此步骤包括生成code_verifier 并计算code_challenge,然后将其作为查询参数发送。

  2. 如果用户未通过身份验证,授权服务器将重定向到登录页面。 身份验证后,用户将再次重定向回授权端点。

  3. 如果用户未同意所请求的范围并且需要同意,则会显示同意页面。

  4. 一旦用户同意,授权服务器会生成一个authorization_code并通过redirect_uri重定向回客户端。

  5. 客户端通过查询参数获取authorization_code并向Token Endpoint发起请求。 对于公共客户端,此步骤包括发送code_verifier参数而不是用于身份验证的凭据。

Vue项目中修改内容

安装crypto-js依赖

已安装可以忽略,该依赖是为了计算Code Challenge使用

npm install crypto-js

TypeScript下额外添加@types/crypto-js依赖

npm install @types/crypto-js

编写公共方法

编写Code Verifier生成与Code Challenge的计算方法

创建PKCE工具js文件

import CryptoJS from 'crypto-js'/*** 生成 CodeVerifier** return CodeVerifier*/
export function generateCodeVerifier() {return generateRandomString(32)
}/*** 生成随机字符串* @param length 随机字符串的长度* @returns 随机字符串*/
export function generateRandomString(length: number) {let text = ''const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'for (let i = 0; i < length; i++) {text += possible.charAt(Math.floor(Math.random() * possible.length))}return text
}/*** 生成 Code Challenge* @param code_verifier 上边生成的 CodeVerifier* @returns Code Challenge*/
export function generateCodeChallenge(code_verifier: string) {return base64URL(CryptoJS.SHA256(code_verifier))
}/*** 将字符串base64加密后在转为url string* @param str 字符串* @returns bese64转码后转为url string*/
export function base64URL(str: CryptoJS.lib.WordArray) {return str.toString(CryptoJS.enc.Base64).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_')
}/*** 将字符串加密为Base64格式的* @param str 将要转为base64的字符串* @returns 返回base64格式的字符串*/
export function base64Str(str: string) {return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(str));
}

编写获取地址栏参数方法

略,已在上篇文章中贴出

编写请求Token方法

略,已在上篇文章中贴出

在环境变量配置文件中添加配置

# 认证服务地址(token签发地址)
VITE_OAUTH_ISSUER=http://127.0.0.1:8080
# PKCE流程使用的客户端Id
VITE_PKCE_CLIENT_ID=pkce-message-client
# 授权码模式使用的回调地址
VITE_PKCE_REDIRECT_URI=http://127.0.0.1:5173/PkceRedirect

创建处理回调的页面PkceRedirect.vue

页面加载时会尝试从地址栏获取参数code,如果能获取到说明是从认证服务回调过来的,执行换取token流程,如果没有获取到code说明需要发起授权申请。跟之前的授权码流程是一致的。

<script setup lang="ts">
import router from '../../router'
import { getToken } from '@/api/Login'
import { getQueryString } from '@/util/GlobalUtils'
import { createDiscreteApi } from 'naive-ui'
import { generateCodeVerifier, generateCodeChallenge } from '@/util/pkce'const { message } = createDiscreteApi(['message'])// 生成CodeVerifier
let codeVerifier: string = generateCodeVerifier()
// codeChallenge
let codeChallenge: string = generateCodeChallenge(codeVerifier)
// 生成state
let state: string = generateCodeVerifier()// 获取地址栏授权码
const code = getQueryString('code')if (code) {// 从缓存中获取 codeVerifierconst state = localStorage.getItem('state')// 校验state,防止corsconst urlState = getQueryString('state')if (urlState !== state) {message.warning('state校验失败.')} else {// 从缓存中获取 codeVerifierconst code_verifier = localStorage.getItem('codeVerifier')getToken({grant_type: 'authorization_code',client_id: import.meta.env.VITE_PKCE_CLIENT_ID,redirect_uri: import.meta.env.VITE_PKCE_REDIRECT_URI,code,code_verifier,state}).then((res: any) => {localStorage.setItem('accessToken', JSON.stringify(res))router.push({ path: '/' })}).catch((e) => {message.warning(`请求token失败:${e.data.error || e.message || e.statusText}`)})}
} else {// 缓存statelocalStorage.setItem('state', state)// 缓存codeVerifierlocalStorage.setItem('codeVerifier', codeVerifier)window.location.href = `${import.meta.env.VITE_OAUTH_ISSUER}/oauth2/authorize?response_type=code&client_id=${import.meta.env.VITE_PKCE_CLIENT_ID}&redirect_uri=${encodeURIComponent(import.meta.env.VITE_PKCE_REDIRECT_URI)}&scope=message.write%20message.read&code_challenge=${codeChallenge}&code_challenge_method=S256&state=${state}`
}
</script><template>加载中...</template>

添加路由

{path: '/PkceRedirect',name: 'PkceRedirect',component: () => import('../views/login/PkceRedirect.vue')
}

认证服务修改内容

在数据库中添加对应客户端的回调地址

重要:例如文中的就需要给客户端pkce-message-client添加一个回调地址http://127.0.0.1:5173/PkceRedirect

重要:例如文中的就需要给客户端pkce-message-client添加一个回调地址http://127.0.0.1:5173/PkceRedirect

重要:例如文中的就需要给客户端pkce-message-client添加一个回调地址http://127.0.0.1:5173/PkceRedirect

经过以上配置授权码模式的对接就完成了,接下来就可以测试了,在首页或者需要触发登录的地方添加一个按钮,点击跳转到/PkceRedirect之后会自动引导发起授权申请流程。

最后

一直都有提到PKCE流程是授权码流程的扩展,通过这两篇文章也可以看出两种流程的授权申请流程基本是一样的,只不过PKCE将客户端密钥换成了code_verifiercode_challenge,虽然稍微麻烦了些,但是安全性也提高了很多;至于移动app或者pc端应用对接的流程也是一样的,只不过是将回调地址换成了URLSchema,其它都是一样的;测试的流程与授权码模式基本一致,这里就不带大家测试了,读者可自行测试,然后观察请求跳转情况。

这里贴一张获取token成功的图片

获取token成功

如果有什么问题可以在评论区指正,谢谢

附录

代码仓库地址:Gitee

文档地址:How-to: Authenticate using a Single Page Application with PKCE

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

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

相关文章

wpf资源Resources探究性学习(一)

测试环境&#xff1a; vistual studio 2017 .net framework 3.5 window 10 新建WPF应用(.net framework)&#xff0c;项目名称为&#xff1a;WpfDemo&#xff0c;如下图&#xff1a; 新建完项目后&#xff0c;默认带有一个名为MainWindow.xaml的代码 一 简单使用字符串资源…

1_图神经网络GNN基础知识学习

文章目录 安装PyTorch Geometric安装工具包 在KarateClub数据集上使用图卷积网络 (GCN) 进行节点分类两个画图函数Graph Neural Networks数据集&#xff1a;Zacharys karate club network.PyTorch Geometric数据集介绍 edge_index使用networkx可视化展示 Graph Neural Networks…

(并查集) 1971. 寻找图中是否存在路径 ——【Leetcode每日一题】

❓ 1971. 寻找图中是否存在路径 难度&#xff1a;简单 有一个具有 n 个顶点的 双向 图&#xff0c;其中每个顶点标记从 0 到 n - 1&#xff08;包含 0 和 n - 1&#xff09;。图中的边用一个二维整数数组 edges 表示&#xff0c;其中 edges[i] [ui, vi] 表示顶点 ui 和顶点 …

Flash的学习

Flash的学习 1 概述 2 特性 STM32 的内部FLASH 包含主存储器、系统存储器以及选项字节区域。 2.1 主存储器 主存储器分为256 页&#xff0c;每页大小为2KB&#xff0c;共512KB。这个分页的概念&#xff0c;实质就是FLASH 存储器 的扇区&#xff0c;与其它FLASH 一样&…

UWB定位模块

UWB定位模组是华星智控自研的小尺寸高集成度模组&#xff0c;模组长宽厚为30.1513.955.62毫米&#xff0c;天线采用IPEX接口分体式设计&#xff0c;方便集成于您的产品中&#xff0c;产品采用本安设计&#xff0c;可以用于煤矿等井下场景&#xff0c;通信距离>100米&#xf…

什么是API接口?API接口的类型,如何调用API接口?

当今互联网技术的发展越来越快&#xff0c;越来越多的网站和应用程序需要获取外部数据来提供更好的服务和用户体验&#xff0c;这就需要使用API接口。本文将会对API接口的概念、类型以及如何调用API接口进行简要介绍。 一、什么是API接口&#xff1f; API&#xff08;Applica…

不可忽视的PG表膨胀优化

我是一个目录 案例1. 什么是表膨胀&#xff1f;2. 表膨胀危害是什么&#xff1f;3. 表膨胀是怎么产生的&#xff1f;4. 如何优化膨胀表&#xff1f; 案例 先来看一例公有云服务登录web页面端卡住案例&#xff1a; 故障现象&#xff1a;WEB端登录非常缓慢&#xff0c;需要耗时5…

【AD】【PCB封装规范计划】 -CON排针类

像这种CON&#xff0c;排针的。画PCB封装的时候&#xff0c;要把数字用丝印标出来&#xff01;&#xff01;&#xff01;

如何使用 Node.js和Express搭建服务器?

如何使用NodeJs搭建服务器 1. 准备工作1.1 安装Node.js 2. 安装express2.1 初始化package.json2.2 安装express2.3 Express 应用程序生成器 1. 准备工作 1.1 安装Node.js Node.js 是一个开源、跨平台的 JavaScript 运行时环境。 下载链接&#xff1a;Node.js官网下载 建议下…

Java面试常用函数

1. charAt() 方法用于返回字符串指定索引处的字符。索引范围为从 0 到 length() - 1。 map.getOrDefault(num, 0) :如果map存在num这个key&#xff0c;则返回num对应的value&#xff0c;否则返回0. Arrays.sort(nums); 数组排序 Arrays.asList("a","b",&q…

Xilinx ZYNQ 7000学习笔记五(Xilinx SDK 烧写镜像文件)

概述 前面几篇讲了ZYNQ7000的启动过程&#xff0c;包括BootRom和FSBL的代码逻辑&#xff0c;其中关于FSBL代码对启动模式为JTAG被动启动没有进行分析&#xff0c;本篇将通过将JTAG的功能和通过Xilinx SDK烧写镜像文件到flash来顺道把FSBL中的JTAG代码部分给讲解下。 1.JTAG …

NuttX实时操作系统介绍(最详细)

比起安卓、iOS、鸿蒙等&#xff0c;NuttX知名度不算高&#xff0c;该系统于2007年由Gregory Nutt先生正式开源。发展至今&#xff0c;NuttX以功能丰富、性能稳定、商业化成熟度高赢得了市场的认可。 NuttX是一个成熟的实时操作系统&#xff0c;于07年由Gregory Nutt先生正式开源…

学习笔记-接口测试(postman、jmeter)

目录 一、什么是接口测试 二、前端和后端 三、get请求和post请求的区别 四、cookie和session 五、接口测试的依据 六、HTTP状态码 七、通用接口用例 八、postman接口测试 九、Jmeter接口测试 一、什么是接口测试 通常做的接口测试指的是系统对外的接口&#xff0c;比…

机器学习:PCA(Principal Component Analysis主成分)降维

参考&#xff1a;PCA降维原理 操作步骤与优缺点_TranSad的博客-CSDN博客 PCA降维算法_偶尔努力翻身的咸鱼的博客-CSDN博客 需要提前了解的数学知识&#xff1a; 一、PCA的主要思想 PCA&#xff0c;即主成分分析方法&#xff0c;是一种使用最广泛的数据降维算法。PCA的主要思想…

【element-ui】el-date-picker 之picker-options时间选择区间禁用效果的实现

element-ui 时间选择器的时间区间禁用dom层引入:picker-option <el-date-pickerv-model"searchFormObj.workTime"clearablevalue-formate"yyyy-MM-dd":picker-options"pickerOptions"placeholder"请选择时间" ></el-date-pi…

基于深度强化学习的四旋翼无人机航线跟随

源自&#xff1a;指挥与控制学报 作者&#xff1a;杨志鹏 李波 甘志刚 梁诗阳 “人工智能技术与咨询” 发布 摘 要 针对无人机在空中执行航线跟随任务时无法对未知环境作出合理应对措施等问题, 提出了一种基于深度强化学习的四 旋翼无人机航线跟随方法. 通过无人机受力…

SpringMVC之JSON数据返回与异常处理机制---全方面讲解

一&#xff0c;JSON数据返回的理解 在Spring MVC中&#xff0c;当需要将数据以JSON格式返回给客户端时&#xff0c;可以使用ResponseBody注解或RestController注解将Controller方法的返回值直接转化为JSON格式并返回。这使得开发者可以方便地将Java对象转换为JSON&#xff0c;并…

【C++】STL之vector操作

文章目录 简介vector中的成员类型模板参数头文件的包含构造函数vector的访问方式&#xff1a;下标[ ]迭代器范围for 交换swap 简介 vector是stl中的一种数组容器&#xff0c;vector在英文中有矢量的意思&#xff0c;但实际上在数据结构中就是一种类似于数组的结构&#xff1b;…

AI大模型服务应用场景

大模型是指模型具有庞大的参数规模和复杂程度的机器学习模型。在深度学习领域&#xff0c;大模型通常是指具有数百万到数十亿参数的神经网络模型。这些模型通常在各种领域&#xff0c;例如自然语言处理、图像识别和语音识别等&#xff0c;表现出高度准确和广泛的泛化能力。伴随…

Jmeter系列-定时器Timers的基本介绍(11)

简介 JMeter中的定时器&#xff08;Timer&#xff09;是一种重要的元件&#xff0c;用于模拟用户在不同时间间隔内发送请求的场景。通过使用定时器&#xff0c;可以模拟负载、并发和容量等不同情况下的请求发送频率。 使用定时器 可以在取样器下添加定时器&#xff0c;这样定…