前言:
在做服务时token验证是必不可少的一环。今天搞node验证可谓是一波三折。
先说踩得坑吧:
在使用express-jwt插件验证token是否过期时,一直验证不通过,报401。
服务端会提示:
原因:就是前端要在token前面加上Bearer和空格。如图:
为什么要加上Bearer和空格呢?
请看express-jwt源码里是如何获取token的
//1 从options中获取token 这个忽略 因为 在设置 需要保护的API 时 并没有传递 getToken 这个方法
if (options.getToken && typeof options.getToken === 'function') {
try {
token = options.getToken(req);
} catch (e) {
return next(e);
}
//2 从authorization中获取token
} else if (req.headers && req.headers.authorization) {
// --这是关键代码-----开始切割--------->
var parts = req.headers.authorization.split(' ');
if (parts.length == 2) {
var scheme = parts[0];
var credentials = parts[1];
if (/^Bearer$/i.test(scheme)) {
token = credentials; // <-------最终获取到token---------
} else {
if (credentialsRequired) {
return next(new UnauthorizedError('credentials_bad_scheme', { message: 'Format is Authorization: Bearer [token]' }));
} else {
return next();
}
}
//3 以上两个途径都没有token时 就报错呗
} else {
return next(new UnauthorizedError('credentials_bad_format', { message: 'Format is Authorization: Bearer [token]' }));
}
}
接下来看下两个插件(时间有限我只简单的说)详细了解看下面。
jsonwebtoken:JSON Web Token 入门教程 - 阮一峰的网络日志
express-jwt:express-jwt - npm
一:jsonwebtoken
jsonwebtoken是我们用于生成token和验证客户端和服务端的token是否一致的。
使用方式:
①安装:
npm install jsonwebtoken
②导入
const jwt = require('jsonwebtoken')
const scret = 'knowledge'; //自定义秘钥 自定义
let setToken = function(str1,str2){
let user = str1; //登录账号和密码作为了规则
let paswd = str2;
const rule = {
username: user,
pwd: paswd
}
//expiresIn:过期时间
let ztoken = jwt.sign(rule, scret, { expiresIn: 60*60*24 })
return ztoken
}
module.exports.setToken = setToken
③路由中使用
const express =require('express')
const userCollection = require('../model/userInfo_model.js')
const userInfoRouter = express.Router();
//自己写的工具方法,只是处理返回结果的,无关紧要
const responseUntil = require('../until/response_until.js')
const {setToken} = require('../until/jwt_token.js')
userInfoRouter.post('/login', (req,res,next)=>{
let params={
name:req.body.name,
password:req.body.password
}
//token返回给客户端
userCollection.findOne(params).then(result=>{
let resObj={
token:setToken(req.body.name,req.body.password),
result
}
res.send(responseUntil(resObj))
})
})
module.exports=userInfoRouter
④截图:
这样一个token就ok了,客户端请求也可以拿到了。
二:接下来就开始第二步。token验证:
①:使用中间件对请求进行拦截获取请求头的token
验证的方法:
const jwt = require('jsonwebtoken')
const scret = 'knowledge'; //自定义秘钥 自定义,没要求
//async await 解决异步请求获取不到问题
let verifyToken = async function(token){
await jwt.verify(token, scret, function (err, data) {
if (err) return false
else return true
})
}
module.exports.verifyToken = verifyToken
导入:
const {verifyToken} = require('./until/jwt_token.js')
app.use((req,res,next)=>{
//获取header中的token,并验证
if(req.headers.authorization){
const flag=verifyToken(req.headers.authorization)
//验证失败
if(!flag){
res.send({status:'fail'})
}
}
//验证成功继续
next()
})
三:验证token的是否过期
①:安装express-jwt
npm install express-jwt
②:使用
const expressJWT = require('express-jwt');//验证token是否失效
app.use(expressJWT({
secret: 'knowledge',//秘钥和生成token的保持一致
algorithms: ['HS256'] //签名算法(6.0以上版本必须加,否则报错)
}).unless({
path: ['/user/login']//登录接口不验证
}))
//捕获错误的全局中间件
app.use(function (err, req, res, next) {
//token过期
if (err.status == 401) {
res.status(401).send({status:'fail'});
return
}
if(err){
res.status(500).send({status:'fail'});
}
});
结尾:
到此就完毕了,这么重要的步骤网上很少有答案的。也许和node做服务用的比较少吧。哈哈。