SAS-Vue-Authorization-Code
一、Vue单页面项目使用授权码模式对接流程说明
以下流程摘抄自官网
在本例中为授权代码流程。 授权码流程的步骤如下:
-
客户端通过重定向到授权端点来发起 OAuth2 请求。
-
如果用户未通过身份验证,授权服务器将重定向到登录页面。 身份验证后,用户将再次重定向回授权端点。
-
如果用户未同意所请求的范围并且需要同意,则会显示同意页面。
-
一旦用户同意,授权服务器会生成一个
authorization_code并通过redirect_uri重定向回客户端。 -
客户端通过查询参数获取
authorization_code并向Token Endpoint发起请求。
二、Vue项目中修改内容
1. 安装crypto-js依赖
已安装可以忽略,该依赖是为了计算Code Challenge和base64加密使用
npm install crypto-js
2. TypeScript下额外添加@types/crypto-js依赖
npm install @types/crypto-js
3. 编写公共方法
1. 生成随机字符串
generateCodeVerifier 函数主要是为了给PKCE流程使用,下篇文章中会说明,这里借用一下生成state,因为本质上是生成随机字符串
/**
* 生成 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
}
2. 编写base64加密方法
/**
* 将字符串加密为Base64格式的
* @param str 将要转为base64的字符串
* @returns 返回base64格式的字符串
*/
export function base64Str(str: string) {
return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(str));
}
3. 编写获取地址栏参数方法
/**
* 根据参数name获取地址栏的参数
* @param name 地址栏参数的key
* @returns key对用的值
*/
export function getQueryString(name: string) {
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')
const r = window.location.search.substr(1).match(reg)
if (r != null) {
return decodeURIComponent(r[2])
}
return null
}
4. 编写请求Token方法
/**
* 从认证服务获取AccessToken
* @param data 获取token入参
* @returns 返回AccessToken对象
*/
export function getToken(data: any) {
const headers: any = {
'Content-Type': 'application/x-www-form-urlencoded'
}
// 这里这么写是为了兼容PKCE与授权码模式
if (data.client_secret) {
// 设置客户端的basic认证
headers.Authorization = `Basic ${base64Str(`${data.client_id}:${data.client_secret}`)}`
// 移除入参中的key
delete data.client_id
delete data.client_secret
}
// 可以设置为AccessToken的类型
return loginRequest.post<any>({
url: '/oauth2/token',
data,
headers
})
}