前端Token?組成及生成方法示例詳解
正文
平常前端項(xiàng)目中,我們通常使用 token 來(lái)進(jìn)行身份驗(yàn)證 —— 客戶(hù)登錄成功,接口就會(huì)返回一個(gè) token,之后前端每次發(fā)送請(qǐng)求就在請(qǐng)求頭中添加個(gè)值為 token 的 authorization 字段來(lái)表明身份。至于 token 是怎么生成的?那一長(zhǎng)串的字母數(shù)字到底有什么含義?或許一些身為前端的小伙伴們長(zhǎng)久以來(lái)并不甚了解。那么本文,就來(lái)對(duì) token 的組成及生成方法做個(gè)基本的介紹吧。
生成 token
在使用 koa 搭建的后端項(xiàng)目中,可以安裝 jsonwebtoken 這個(gè)庫(kù)來(lái)生成 token:
npm i jsonwebtoken
之后引入 jwt,通過(guò) jwt.sign() 即可得到 token,傳入的第一個(gè)參數(shù)是 token 攜帶的信息,第二個(gè)參數(shù)是用于數(shù)字簽名的密鑰,第三個(gè)參數(shù)可以傳入一些配置,比如過(guò)期時(shí)間 expiresIn,單位為秒:
// 代碼片段一,省略部分代碼
const jwt = require('jsonwebtoken')
loginRouter.get('/login', (ctx, next) => {
const token = jwt.sign({ name: 'Jay' }, 'aaabbbccc', { expiresIn: 60 * 60 })
ctx.body = {
msg: '登錄成功',
token
}
})
使用瀏覽器發(fā)送請(qǐng)求,可以看到生成的 token:

token 的組成
我們可以將生成的 token 復(fù)制粘貼到 jwt 官網(wǎng)的 debugger 工具里進(jìn)行解碼:

可以發(fā)現(xiàn) token 使用 . 分割成了 3 部分:
1. Header
即 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 這部分,為 Base64 編碼后的結(jié)果,其中有兩個(gè)屬性:
alg,也就是 Algorithm(算法) 的縮寫(xiě),指定加密算法,默認(rèn)為 HS256(HMAC-SHA256),是一種單項(xiàng)散列函數(shù),加密解密采用同個(gè)密鑰;typ,token 的類(lèi)型(type),通??梢怨潭▽?xiě)成 JWT。
所以這部分結(jié)果,如果保持代碼片段一不變,瀏覽器每次重新請(qǐng)求得到的結(jié)果也都不會(huì)變化。
2. Payload
token 攜帶的數(shù)據(jù),除了我們?cè)诖a片段一中傳入的 name 信息以及過(guò)期時(shí)間 exp ,還有默認(rèn)攜帶的 iat(issued at),為 token 的簽發(fā)時(shí)間。Payload 部分的數(shù)據(jù)同樣是經(jīng)過(guò) Base64 編碼的。
3. Signature
簽名部分,通過(guò) HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secret) 得到,即將 Header 和 Payload 的 Base64 編碼結(jié)果與數(shù)字簽名的密鑰 secret 結(jié)合,通過(guò) HS256 算法生成,這部份的結(jié)果,瀏覽器每次重新請(qǐng)求時(shí)都會(huì)重新生成。
驗(yàn)證 token
假定前端是通過(guò) Bearer Token 類(lèi)型向服務(wù)器傳遞的 token,實(shí)際上就是將 token 賦值給請(qǐng)求頭的 authorization 屬性。那么后端在驗(yàn)證時(shí),可以通過(guò) ctx.headers.authorization 拿到帶有 Bearer 前綴(注意 Bearer 后有個(gè)空格)的 token 。之后再將獲取的 token 以及代碼片段一生成 token 時(shí)傳入的密鑰一起傳給 jwt.verify(),如果驗(yàn)證成功,則 res 可以得到 Payload 數(shù)據(jù);如果驗(yàn)證失敗,則會(huì)報(bào)錯(cuò),可用 try catch 捕獲 :
// 代碼片段二
userRouter.get('/center', (ctx, next) => {
const authorization = ctx.headers.authorization
const token = authorization.replace('Bearer ', '')
try {
const res = jwt.verify(token, 'aaabbbccc')
console.log('res', res) // res { name: 'Jay', iat: 1679814009, exp: 1679817609 }
ctx.body = '驗(yàn)證成功'
} catch (error) {
ctx.body = '驗(yàn)證失敗'
}
})
采用非對(duì)稱(chēng)加密算法
在代碼片段一中使用 jwt 生成 token 時(shí),默認(rèn)采用的加密算法是 HS256,安全性不高,所以一般公司里的項(xiàng)目采用的都是非對(duì)稱(chēng)加密算法,比如 RSA 算法,使用私鑰來(lái)頒發(fā) token,使用公鑰來(lái)驗(yàn)證 token,關(guān)于加密算法這部分知識(shí),若想了解更多,可移步 《前端加密》。
生成公私密鑰
在 windows 系統(tǒng)下,公私密鑰的生成可以去下載安裝 OpenSSL, 然后通過(guò)系統(tǒng)自帶的命令行工具使用 openssl 生成。也可以直接通過(guò) git 的 bash 工具(集成了 OpenSSL)來(lái)生成 。首先生成私鑰: 進(jìn)入到要保存密鑰的目錄下,輸入 openssl 按下回車(chē):

接著就可以輸入 genrsa -out private.key 1024 來(lái)生成 rsa 算法的私鑰:

生成的私鑰如下:

有了私鑰,再使用 rsa -in private.key -pubout -out public.key 生成與之對(duì)應(yīng)的公鑰:

公鑰如下:

修改之前的代碼
有了一對(duì)公私密鑰后,生成 token 時(shí)我們就可以將代碼片段一稍加修改,將傳入的密鑰改為私鑰,并在配置對(duì)象中指定要使用的算法為 RS256:
const token = jwt.sign({ name: 'Jay' }, privateKey, {
expiresIn: 60 * 60,
algorithm: 'RS256'
})
驗(yàn)證 token 時(shí),也需將代碼片段二中用公鑰替換原本的密鑰,然后添加算法配置,只不過(guò)這里 algorithm 的值為數(shù)組,因?yàn)樵隍?yàn)證時(shí)是可以通過(guò)多種算法依次嘗試的:
const res = jwt.verify(token, publicKey, {
algorithm: ['RS256']
})
privateKey 和 publicKey 可以通過(guò) fs 模塊獲?。?/p>
const fs = require('fs')
const privateKey = fs.readFileSync('./src/keys/private.key')
const publicKey = fs.readFileSync('./src/keys/public.key')以上就是前端Token 組成及生成方法示例詳解的詳細(xì)內(nèi)容,更多關(guān)于前端Token組成生成方法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Three.js實(shí)現(xiàn)3D機(jī)房效果
這篇文章主要為大家詳細(xì)介紹了Three.js實(shí)現(xiàn)3D機(jī)房效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12
微信小程序?qū)崿F(xiàn)選擇內(nèi)容顯示對(duì)應(yīng)內(nèi)容
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)選擇內(nèi)容顯示對(duì)應(yīng)內(nèi)容,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07
document.onreadystatechange事件的用法分析
這里主要介紹document.onreadystatechange事件的使用方法, 一般多用于實(shí)時(shí)監(jiān)控用戶(hù)的輸入2009-10-10
gulp-uglify 與gulp.watch()配合使用時(shí)報(bào)錯(cuò)(重復(fù)壓縮問(wèn)題)
gulp是基于Nodejs的自動(dòng)任務(wù)運(yùn)行器,gulp 和 grunt 非常類(lèi)似,但相比于 grunt 的頻繁 IO 操作,gulp 的流操作,能更快地更便捷地完成構(gòu)建工作。今天在學(xué)習(xí)gulp時(shí)遇到當(dāng)用gulp.watch來(lái)監(jiān)聽(tīng)js文件的變動(dòng)時(shí)出現(xiàn)重復(fù)壓縮問(wèn)題,下面小編給大家解答下2016-08-08
微信小程序 連續(xù)旋轉(zhuǎn)動(dòng)畫(huà)(this.animation.rotate)詳解
這篇文章主要介紹了微信小程序 連續(xù)旋轉(zhuǎn)動(dòng)畫(huà)(this.animation.rotate)詳解的相關(guān)資料,需要的朋友可以參考下2017-04-04
微信小程序 scroll-view實(shí)現(xiàn)錨點(diǎn)滑動(dòng)的示例
本篇文章主要介紹了微信小程序 scroll-view實(shí)現(xiàn)錨點(diǎn)滑動(dòng)的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
JavaScript解析任意形式的json樹(shù)型結(jié)構(gòu)展示
這篇文章主要介紹了JavaScript解析任意形式的json樹(shù)型結(jié)構(gòu)展示的相關(guān)資料,需要的朋友可以參考下2017-07-07

