從零搭建個(gè)人博客(四)-集成jwt

網(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)用 jwtverify 方法即可

我們現(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

jwt1.png

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

jwt2.png

還有種方法直接點(diǎn)擊 Authorization 選擇 Bearer Token 然后直接輸入 token 點(diǎn)擊發(fā)送即可

JWT 在線驗(yàn)簽

我們可以進(jìn)入 JWT.IO 輸入 token 和 secret 進(jìn)行在線驗(yàn)簽

jwt3.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容