- 為什么使用 JWT
- 集成 jwt
- 生成 token
- 編寫 Auth 中間件
- 在接口中進(jìn)行攔截
- 使用 koa-jwt
- 用postmen 進(jìn)行調(diào)試 JWT
- JWT 在線驗(yàn)簽
網(wǎng)上有很多關(guān)于 jwt 的介紹,這里不做敘述,總結(jié)有以下優(yōu)勢(shì):
- 安全性高,防止token被偽造和篡改
- 支持跨域訪問: Cookie是不允許垮域訪問的,這一點(diǎn)對(duì)Token機(jī)制是不存在的,前提是傳輸?shù)挠脩粽J(rèn)證信息通過HTTP頭傳輸.
- 無狀態(tài):Token機(jī)制在服務(wù)端不需要存儲(chǔ)session信息,因?yàn)門oken 自身包含了所有登錄用戶的信息,只需要在客戶端的cookie或本地介質(zhì)存儲(chǔ)狀態(tài)信息.
- 去耦: 不需要綁定到一個(gè)特定的身份驗(yàn)證方案。Token可以在任何地方生成,只要在你的API被調(diào)用的時(shí)候,你可以進(jìn)行Token生成調(diào)用即可.
集成 jwt
安裝依賴
npm install jsonwebtoken
生成 token
在 config 文件里面配置 秘鑰(secret) 和 過期時(shí)間
...
security: {
secretKey: 'xikun',
expiresIn: 60 * 60
}
jwt.sign(payload, secretOrPrivateKey, [options, callback])
- payload 必須是一個(gè)object, buffer或者string
- 我們配置的秘鑰
- 各種配置
封裝生成token 的方法
const generateToken = (uid, scope) => {
const token = jwt.sign({
uid,
scope
}, secretKey, {
expiresIn
})
return token
}
假如我們?cè)谟脩舻卿浲瓿珊笊闪?token 并且返回了token 給前端,前端下次攜帶 token 來,我們?nèi)绾谓邮詹?duì)其校驗(yàn)?zāi)?
編寫 Auth 中間件
在我們的接口中,有的需要接口需要登錄后才能訪問,有的不需要,因此我們必須來進(jìn)行區(qū)分一下. 如下,我們來編寫一個(gè)中間件來獲取 token 并進(jìn)行校驗(yàn)
class Auth {
/**
* token 驗(yàn)證
* @param {*} token
*/
static verifyToken(token) {
try {
jwt.verify(token, secretKey)
return true
} catch (error) {
return false
}
}
}
驗(yàn)證 token 是否正確 只需要調(diào)用 jwt 的 verify 方法即可
我們現(xiàn)在再編寫一個(gè)方法獲取 headers 里面的 authorization 加密生成的簽名
/**
* 獲取請(qǐng)求頭Authorization 上的token
* @param {*} ctx
*/
static resolveAuthorizationHeader(ctx) {
if (!ctx.req.headers || !ctx.req.headers.authorization) {
return false
}
const parts = ctx.header.authorization.split(' ');
if (parts.length === 2) {
const scheme = parts[0];
const credentials = parts[1];
if (/^Bearer$/i.test(scheme)) {
return credentials;
}
}
return false
}
我們給 Auth 添加一個(gè) get 方法
get verifyToken() {
return async (ctx, next) => {
// 獲取token
const token = Auth.resolveAuthorizationHeader(ctx)
if (!token) {
throw new AuthFaild('Bad Authorization header format. Format is "Authorization: Bearer <token>"')
}
let errMsg = "token 不合法"
// token 驗(yàn)證
try {
var decode = jwt.verify(token, secretKey)
} catch (error) {
if (error.name === 'TokenExpiredError') {
errMsg = 'token 已過期請(qǐng)重新登錄'
}
throw new AuthFaild(errMsg)
}
await next()
}
}
編寫完了中間件如何使用呢,下來我們?cè)诮涌谥芯唧w使用下:
在接口中進(jìn)行攔截
一個(gè)不要登錄就能訪問的接口如下:
const router = new Router({
prefix: '/user'
})
router.post('/login', async (ctx) => {
// do
})
現(xiàn)在突然來了一個(gè)需要登錄才能訪問的接口,我們可以這樣使用:
const { Auth } = require('../../services/auth')
router.get('/:uid', new Auth().verifyToken, async (ctx) => {
const { uid } = ctx.params
if (!uid) {
throw new ParameterException('uid必填!')
}
const res = await UserController.findByUid(uid)
throw new Success(res)
})
OK , 這樣我們就集成了 jwt 和完成了基本的登陸權(quán)限。具體使用方法 請(qǐng)查看 jsonwebtoken
使用 koa-jwt
如何你覺得上面的步驟太過于繁瑣,你可以集成 koa-jwt 來完成上面繁瑣的步驟
npm install koa-jwt
koa-jwt 使用 非常方面,只需要幾行代碼便能幫我們實(shí)現(xiàn) 生成token,驗(yàn)證token,接口攔截等一系列操作.
var Koa = require('koa');
var jwt = require('koa-jwt');
var app = new Koa();
app.use(jwt({ secret: 'shared-secret' }).unless({ path: [/^\/public/] }));
unless 可以填入多個(gè)路徑表示 以該路徑開頭 不進(jìn)行 token 校驗(yàn)的。更多功能請(qǐng)查看 koa-jwt
用postmen 進(jìn)行調(diào)試 JWT

在 Headers 里面配置 Authorization Value 填入 Bearer + 空格 + token ,記住 Bearer 后面必須要有空格 因?yàn)檫@是 jwt 的約定方式

還有種方法直接點(diǎn)擊 Authorization 選擇 Bearer Token 然后直接輸入 token 點(diǎn)擊發(fā)送即可
JWT 在線驗(yàn)簽
我們可以進(jìn)入 JWT.IO 輸入 token 和 secret 進(jìn)行在線驗(yàn)簽
