实现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;