第一点:出现令牌验证失败,是因为设置了错误处理中间件,这是正常的。
app.use((err, req, res, next) => {
// token校验不通过提示
if (err.name === "UnauthorizedError") {
console.log("token已失效,重新登录",err);
return res.send(Response.error("token已失效,重新登录", states.AUTH_ERROR))
}
// 打印异常
console.log("异常信息:", err);
// 设置http响应的状态码,响应到前端
res.send(Response.error("服务器异常,重新访问", 500))
next()
})
第二:翻阅很多CSDN资料,都只是在教人生成token和配置unless排除列表,难道没人教路由怎么通过JWT验证?这是我这个bug产生的重要原因。
app.use(expressJWT({ credentialsRequired: false,secret: secretKey, algorithms: ["HS256"] }).unless({
path: [
// "/userinfo/get",
"/userinfo/insert",
"/userinfo/login",
// "/userinfo/get",
]
}))
第三:其中还有一个原因:生成token时没有使用正确的格式,正确的格式应该在密钥之前加上 'Bearer ' + 密钥。(血泪教训),如果不加'bearer ',jwt会直接验证失败,注意bearer后面有空格,
function generateToken(d_admin) {
// 生成token使用jwt的sign方法
return 'Bearer ' + jwt.sign({username : d_admin}, secretKey, { expiresIn })
}
第四:最关键一点,第二点的代码似乎是在配置拦截规则,所以基本上所有的路由都会被拦截(除了unless中的排除路由),此处有点不懂。既然被拦截,那么如何才能让需要验证的路由通过JWT的验证了?
首先,需要配置好路由验证中间件。此处的验证方法调用了我的其他js文件。
const haveToken = (req, res, next) => {
console.log('中间件执行' + req.headers.authorization)
const token = req.headers.authorization
const tokenstr = token.split(' ')[1];
if (token) {
const decode = verifyToken(tokenstr)
if (decode) {
req.user = decode
next()
} else {
res.send({
code: 401,
msg: 'token已过期'
})
}
}
}
其他js代码文件。
/**
* 使用jwt管理token
*/
// 导入jsonwebtoken,生成jwt字符串的模块
const jwt = require("jsonwebtoken")
// 获取密钥
const { secretKey, expiresIn } = require("./config.js")
/**
* 生成token
* @param {String} uid
* @param {Number} scope
* @returns
*/
function generateToken(d_admin) {
// 生成token使用jwt的sign方法
return 'Bearer ' + jwt.sign({username : d_admin}, secretKey, { expiresIn })
}
function verifyToken(token) {
try {
// token认证,使用jwt的verify方法
return jwt.verify(token, secretKey)
} catch (e) {
return false
}
}
module.exports = { generateToken, verifyToken }
最后,需要在我们需要验证的路由身上加上这个中间件!
router.get("/userinfo/get", haveToken,(req, res) => {
// console.log(req.auth)
// console.log('拿到的数据' + req.body)
console.log('数据',req.headers.authorization)
const token = req.auth
res.send({
code: '200',
data: '前端'
})
})
应该完成了,有些地方不是很理解到位希望大佬指正。