• 全栈项目|小书架|服务器开发-NodeJS 使用 JWT 实现登录认证


    通过这篇 全栈项目|小书架|服务器开发-JWT 详解 文章我们对JWT有了深入的了解,那么接下来介绍JWT如何在项目中使用。

    安装

    $ npm install jsonwebtoken
    

    生成 Token

    将生成token的代码封装到一个函数中,方便后续调用。

    /**
     * 生成 token
     * @param {用户 id} uid 
     * @param {*} scope 
     */
    const generateToken = function (uid, scope) {
    	// 配置项中的密钥和过期时间
        const secretKey = global.config.security.secretKey
        const expiresIn = global.config.security.expiresIn
        
        // 接收三个参数,第一个是载荷,用于编码后存储在 token 中的数据,也是验证 token 后可以拿到的数据;
        // 第二个是密钥,自己定义的,验证的时候也是要相同的密钥才能解码;
        // 第三个是options,可以设置 token 的过期时间。
        const token = jwt.sign({
            uid,
            scope
        }, secretKey, {
            expiresIn: expiresIn
        })
        return token
    }
    

    有些api用户是没权限访问,比如用户只有总管理员可以查看统计数据,而普通用户访问会提示权限不足,如何去实现这个功能呢?

    koa是一个中间件框架,那么就可以通过中间件的方式去实现

    拦截器中间件

    1. 定义一个中间件
    2. 在接口访问时调用中间件验证

    Auth.js权限验证中间件

    const basicAuth = require('basic-auth')
    const jwt = require('jsonwebtoken')
    
    class Auth {
        /**
         * @param {用户权限等级} level 
         */
        constructor(level) {
            this.level = level || 1
            Auth.USER = 8
            Auth.ADMIN = 16
            Auth.SUPER_ADMIN = 32
        }
    
        get m() {
            return async (ctx, next) => {
                
                const userToken = basicAuth(ctx.req)
                let errMsg = 'token不合法'
    
                if (!userToken || !userToken.name) {
                    throw new global.errs.Forbidden(errMsg)
                }
                // 校验 token 令牌
                try {
                    var decode = jwt.verify(userToken.name, 
                        global.config.security.secretKey)
                } catch (error) {
                    if (error.name == 'TokenExpiredError'){
                        errMsg = 'token已过期'
                    }
                    // token不合法
                    throw new global.errs.Forbidden(errMsg)
                }
    
                if(decode.scope < this.level){
                    errMsg = '权限不足'
                    throw new global.errs.Forbidden(errMsg)
                }
    
                // uid,scope
                ctx.auth = {
                    uid:decode.uid,
                    scope:decode.scope
                }
    
                await next()
            }
        }
    
    }
    
    module.exports = {
        Auth
    }
    

    调用中间件验证权限

    router.get('/search/hot',  new Auth().m,async ctx => {
    	ctx.body = {
    		'uid':ctx.auth.uid,
    		'scope': ctx.auth.scope
    	}
    })
    
    

    ps: new Auth().m 中的m不需要括号,因为是属性,不是方法

    验证 Token

    通过调用jwt.verify,判断是否出错,没有出错则token有效,否则token无效。

    在验证token时就可以获取到携带的数据,有两种方式:
    (1)通过 jwt.verify直接返回
    (2)通过 jwt.verify保存在ctx.auth然后需要的时候再返回。

    方式1:

    static verifyToken(token){
            try{
                let userData = {}
                jwt.verify(token, global.config.security.secretKey, (err, data) => {
                    if(err) {
                        throw new global.errs.HttpException("验证失败",-1)
                    } else {
                    	// data 中就包含 jwt.verify 验证通过之后的数据
                        userData =  data
                    }
                })
                return userData
            }
            catch (error){
                throw new global.errs.HttpException("验证失败",-1)
            }
    
        }
    

    方式2:
    通过权限验证之后,就可以在接口请求中获取到数据 jwt中携带的数据了。

    在获取热搜书籍接口中取出先前传递的uidscope

    router.get('/search/hot',  new Auth().m,async ctx => {
    	ctx.body = {
    		'uid':ctx.auth.uid,
    		'scope': ctx.auth.scope
    	}
    })
    
    

    参考


    在这里插入图片描述

  • 相关阅读:
    vue中的ref,refs使用
    setTimeout 为0的作用
    click 和 mousedown 以及map地图的pointerdown
    electron图标
    websocket
    居中
    一键生成vue模板
    IntelliJ IDEA 安装破解及汉化详解
    基础的一些东西
    git 合作开发
  • 原文地址:https://www.cnblogs.com/gdragon/p/11893243.html
Copyright © 2020-2023  润新知