什么是jwt
JWT 英文名是 Json Web Token ,是一種用于通信雙方之間傳遞安全信息的簡(jiǎn)潔的、URL安全的表述性聲明規(guī)范,經(jīng)常用在跨域身份驗(yàn)證。
JWT 以 JSON 對(duì)象的形式安全傳遞信息。因?yàn)榇嬖跀?shù)字簽名,因此所傳遞的信息是安全的。
用戶(hù)認(rèn)證成功后,server端返回一個(gè)加密的token給客戶(hù)端。后續(xù)客戶(hù)端每次請(qǐng)求都會(huì)攜帶這個(gè)token,表明當(dāng)前用戶(hù)身份。
koa2實(shí)現(xiàn)jwt
創(chuàng)建koa項(xiàng)目:koa2 -e blog-koa
安裝koa-jwt插件: npm i koa-jwt -S
安裝加密工具: npm i jsonwebtoken -S
編輯入口:./src/app.js
// ...
// 引入jwt
const koaJwt = require('koa-jwt')
// 引入視圖路由
const errorViewRouter = require('./routes/view/error')
const index = require('./routes/index')
const users = require('./routes/users')
// jwt配置,每次都會(huì)檢測(cè)客戶(hù)端是否攜帶了token(需配置在路由之前),否則返回401
app.use(koaJwt({
secret: 'this-is-a-secret', // 密鑰(自定義)
}).unless({
path: [/^\/users\/login/] // 定義忽略jwt驗(yàn)證的目錄
}))
// ...
編輯路由:./src/routes/users.js
const router = require('koa-router')()
const jwt = require('jsonwebtoken')
const util = require('util')
const verify = util.promisify(jwt.verify)
router.prefix('/users')
router.get('/', function (ctx, next) {
ctx.body = 'this is a users response!'
})
// 模擬登錄
router.post('/login', async function (ctx, next) {
const { userName, password } = ctx.request.body
let userInfo = null
if( userName === 'yat' && password === '123456') {
userInfo = { id: 123, userName: 'yat', nickName: '李四' }
}
if( !userInfo ) {
// 登陸失敗
ctx.body = {code: -1, msg: '用戶(hù)不存在,登錄失敗', data: null}
} else {
// 登陸成功, 加密token
let token = jwt.sign(userInfo, 'this-is-a-secret', {
expiresIn: '1h', // 過(guò)期時(shí)間:1個(gè)小時(shí)
})
ctx.body = {code: 0, msg: 'ok', data: {...userInfo, token}}
}
})
// 獲取用戶(hù)信息
router.get('/userinfo', async function (ctx, next) {
let token = ctx.header.authorization
try {
const payload = await verify(token.split(' ')[1], 'this-is-a-secret')
ctx.body = {code: 0, msg: 'ok', data: payload}
} catch (error) {
ctx.body = {code: -1, msg: '獲取用戶(hù)信息失敗', data: null}
}
})
module.exports = router
Postman驗(yàn)證接口
驗(yàn)證被攔截的路由:http://localhost:3000/users,請(qǐng)求被攔截,返回401。

請(qǐng)求被攔截了
請(qǐng)求登錄接口:http://localhost:3000/users/login

請(qǐng)求登錄接口,獲取服務(wù)端傳過(guò)來(lái)的token
請(qǐng)求獲取用戶(hù)信息接口:http://localhost:3000/users/userinfo
請(qǐng)求頭信息"Authorization": "Bearer eyJhbG...."

通過(guò)解析頭信息token獲取用戶(hù)信息
jwt vs session
- 解決了登錄 & 獲取用戶(hù)信息的問(wèn)題
- 用戶(hù)信息加密和存儲(chǔ)都在客戶(hù)端,不依賴(lài)cookie,可以跨域
- session用戶(hù)信息存儲(chǔ)在服務(wù)端,以來(lái)cookie,不可跨域
- 一般情況,兩者都能滿(mǎn)足。大型系統(tǒng)兩者可共用。
- jwt更加適用于服務(wù)節(jié)點(diǎn)多、跨域多的情況。無(wú)法嚴(yán)格控制用戶(hù)登陸狀態(tài),不需要redis等存儲(chǔ)工具,操作簡(jiǎn)單。
- session更加適用于統(tǒng)一的web服務(wù),server需要嚴(yán)格管理用戶(hù)信息和登陸狀態(tài)的情況。