从零搭建个人博客(四)-集成jwt

网上有很多关于 jwt 的介绍,这里不做叙述,总结有以下优势:

  • 安全性高,防止token被伪造和篡改
  • 支持跨域访问: Cookie是不允许垮域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息通过HTTP头传输.
  • 无状态:Token机制在服务端不需要存储session信息,因为Token 自身包含了所有登录用户的信息,只需要在客户端的cookie或本地介质存储状态信息.
  • 去耦: 不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成,只要在你的API被调用的时候,你可以进行Token生成调用即可.

集成 jwt

安装依赖

npm install jsonwebtoken

生成 token

在 config 文件里面配置 秘钥(secret) 和 过期时间

...
security: {
    secretKey: 'xikun',
    expiresIn: 60 * 60
}

jwt.sign(payload, secretOrPrivateKey, [options, callback])

  • payload 必须是一个object, buffer或者string
  • 我们配置的秘钥
  • 各种配置

封装生成token 的方法

const generateToken = (uid, scope) => {
    const token = jwt.sign({
        uid,
        scope
    }, secretKey, {
        expiresIn
    })

    return token
}

假如我们在用户登录完成后生成了 token 并且返回了token 给前端,前端下次携带 token 来,我们如何接收并对其校验呢?

编写 Auth 中间件

在我们的接口中,有的需要接口需要登录后才能访问,有的不需要,因此我们必须来进行区分一下. 如下,我们来编写一个中间件来获取 token 并进行校验

class Auth {
/**
 * token 验证
 * @param {*} token 
 */
static verifyToken(token) {
    try {
        jwt.verify(token, secretKey)
        return true
    } catch (error) {
        return false
    }
}
}

验证 token 是否正确 只需要调用 jwtverify 方法即可

我们现在再编写一个方法获取 headers 里面的 authorization 加密生成的签名


/**
 * 获取请求头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 添加一个 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 验证
        try {
            var decode = jwt.verify(token, secretKey)
        } catch (error) {
            if (error.name === 'TokenExpiredError') {
                errMsg = 'token 已过期请重新登录'
            }
            throw new AuthFaild(errMsg)
        }
        await next()
    }
}

编写完了中间件如何使用呢,下来我们在接口中具体使用下:

在接口中进行拦截

一个不要登录就能访问的接口如下:

const router = new Router({
    prefix: '/user'
})
router.post('/login', async (ctx) => {
 // do
})

现在突然来了一个需要登录才能访问的接口,我们可以这样使用:


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 和完成了基本的登陆权限。具体使用方法 请查看 jsonwebtoken

使用 koa-jwt

如何你觉得上面的步骤太过于繁琐,你可以集成 koa-jwt 来完成上面繁琐的步骤

npm install koa-jwt

koa-jwt 使用 非常方面,只需要几行代码便能帮我们实现 生成token,验证token,接口拦截等一系列操作.

var Koa = require('koa');
var jwt = require('koa-jwt');

var app = new Koa();

app.use(jwt({ secret: 'shared-secret' }).unless({ path: [/^\/public/] }));

unless 可以填入多个路径表示 以该路径开头 不进行 token 校验的。更多功能请查看 koa-jwt

用postmen 进行调试 JWT

jwt1.png

在 Headers 里面配置 Authorization Value 填入 Bearer + 空格 + token ,记住 Bearer 后面必须要有空格 因为这是 jwt 的约定方式

jwt2.png

还有种方法直接点击 Authorization 选择 Bearer Token 然后直接输入 token 点击发送即可

JWT 在线验签

我们可以进入 JWT.IO 输入 token 和 secret 进行在线验签

jwt3.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容