egg实现token验证

2,890 阅读2分钟

实现token验证

使用jsonwebtoken生成token

github:github.com/auth0/node-…>

npm install jsonwebtoken

使用egg-jwt

github: <github.com/okoala/egg-…

egg-jwt中间件的好处就是直接通过密钥即可验证token

它把我们封装了验证token的逻辑代码

  • JWT身份验证中间件使用JWT令牌对调用方进行身份验证。如果令牌token有效,则ctx.state.user(默认情况下)将设置JSON对象,该对象将解码后供以后的中间件用于授权和访问控制。
  • 利用egg-jwt设置需要验证token才能访问的接口,验证成功后可在上下文中的state中获取状态信息,ctx.state.user 获取用户对象
npm install egg-jwt

config/plugin.js

// egg-jwt
exports.jwt = {
    enable: true,
    package: "egg-jwt"
};

config/config.default.js

module.exports = appInfo => {
  const config = exports = {};
  config.middleware = ['errorHandle'];  
    config.jwt = {
        secret: 'secret', //密钥
       ignore: [/^\/user\/login/], // 哪些请求不需要认证
    }

       return {
        ...config
    };
};

app/router.js

 module.exports = app => {
    const { router, controller } = app;
     //使用egg-jwt中间件来授权,授权成功才会执行下一个中间件
    router.get('/user/authorization', app.jwt, controller.user.auth);  //token授权
   };

app/middleware/error_handle.js

  • 统一错误处理

如果JWT有一个过期(exp),它将被检查。

当token验证异常时候的处理,如token过期、token错误

/**
 * @description: 统一错误处理
 * @code  401 未授权 500:服务器内部错误  422 :状态码是指请求格式正确,但是由于含有语义错误,无法响应。
 * @return: 
 */

module.exports = (options, app) => {
    return async function(ctx, next) {
        try {
            await next()
        } catch (err) {

            // 所有的异常都在 app 上触发一个 error 事件,egg会记录一条错误日志
            ctx.app.emit('error', err, ctx);
            const status = err.status || 500;
            // 生产环境时 500 错误的详细错误内容不返回给客户端,因为可能包含敏感信息
            const error = status === 500 && ctx.app.config.env === 'prod' ?
                'Internal Server Error' :
                err.message;
            if (status === 401) {
                //自定义jwt错误处理
                ctx.body = {
                    code: 401,
                    //token过期或错误
                    msg: "token error"
                }
            } else if (status === 422) {
                //422:请求格式正确,但是由于含有语义错误
                ctx.body.detail = err.errors;
            } else {
                // 从 error 对象上读出各个属性,设置到响应中 
                ctx.body = { error };
                ctx.status = status;
            }


        }


    }
}

app/extend/helper.js

  • 在Helper 函数用来提供一些实用的 utility 工具函数,方便调用
const jwt = require('jsonwebtoken')
module.exports = {
    //生成Token 
    getToken(payload = {}, secret) {
        return jwt.sign(payload, secret, { expiresIn: '1h' });
    }
}

app/controller/user.js

'use strict';
const Controller = require('egg').Controller;
class UserController extends Controller {
    async login() {
            const { ctx, app } = this;
            const { username, password } = ctx.params;
            // const secret = app.config.secret;
            const secret = app.config.jwt.secret
            const token = ctx.helper.getToken({ username }, secret);
            // 模拟
            if (username === '123' && password === '123') {
                ctx.body = {
                    code: 200,
                    message: '登录成功',
                    token,
                }
            } else if (username !== '123') {
                ctx.body = {
                    code: 200,
                    message: '用户名不存在',
                }
            } else if (username === '123', password !== '123') {
                ctx.body = {
                    code: 200,
                    message: '密码错误',
                }
            }

        }
        //token授权
    async auth() {
            const { ctx, app } = this;
            const { username } = ctx.state.user
            const secret = app.config.jwt.secret
            const token = ctx.helper.getToken({ username }, secret);
            ctx.body = {
                code: 200,
                token
            }

        }
  
    
}
module.exports = UserController;