验证时 JWT 令牌始终无效
Posted
技术标签:
【中文标题】验证时 JWT 令牌始终无效【英文标题】:JWT token is always invalid when verified 【发布时间】:2021-02-12 01:41:54 【问题描述】:我是 node.js、express 和 JWT 的新手。我在这里发现了类似的问题,但它们没有帮助。
我能够登录并将令牌存储在本地存储中,但是当我尝试为具有相同令牌的另一个请求设置授权标头时,它在服务器中的验证失败。我从服务器和客户端检查了令牌,它们完全相同,但验证失败,请帮助!
这是我用来验证令牌的代码。
exports.verify = function(req, res, next)
let accessToken = req.headers.authorization
if (!accessToken)
return res.status(403).send()
let payload
try
// Never makes it through this
payload = jwt.verify(accessToken, process.env.ACCESS_TOKEN_SECRET)
next()
catch(e)
return res.status(401).json(success: false, message: "token expired or invalid")
在app.js
文件中,我将verify
这样的函数用于另一条路线。
const verify = require('./controllers/auth')
const userRoutes = require('./routes/userRoutes')
app.use('/user', verify, userRoutes)
我哪里错了?
编辑:
我在verify
函数中添加了console.log(e)
,在catch()
内部得到了以下结果。
TokenExpiredError: jwt 已过期 在/home/shashank/Documents/sms/server/node_modules/jsonwebtoken/verify.js:152:21 在 getSecret (/home/shashank/Documents/sms/server/node_modules/jsonwebtoken/verify.js:90:14) 在 Object.module.exports [作为验证] (/home/shashank/Documents/sms/server/node_modules/jsonwebtoken/verify.js:94:10) 在exports.verify (/home/shashank/Documents/sms/server/controllers/auth.js:62:23) 在 Layer.handle [as handle_request] (/home/shashank/Documents/sms/server/node_modules/express/lib/router/layer.js:95:5) 在 trim_prefix (/home/shashank/Documents/sms/server/node_modules/express/lib/router/index.js:317:13) 在/home/shashank/Documents/sms/server/node_modules/express/lib/router/index.js:284:7 在 Function.process_params (/home/shashank/Documents/sms/server/node_modules/express/lib/router/index.js:335:12) 在下一个(/home/shashank/Documents/sms/server/node_modules/express/lib/router/index.js:275:10) 在 cookieParser (/home/shashank/Documents/sms/server/node_modules/cookie-parser/index.js:57:14) 过期时间:2020-10-29T17:30:31.000Z
让我展示一下我存储密钥信息的 .env 文件
ACCESS_TOKEN_SECRET=swsh23hjddnns
ACCESS_TOKEN_LIFE=3600
REFRESH_TOKEN_SECRET=dhw782wujnd99ahmmakhanjkajikhiwn2n
REFRESH_TOKEN_LIFE=86400
那么,访问令牌必须持续一个小时吧?
令牌的创建如下所示
const jwt = require('jsonwebtoken')
// Not using a database right now.
let users =
email: 'myemail@gmail.com',
password: 'password'
exports.login = function(req, res)
let email = req.body.email
let password = req.body.password
// Simple validation !
if (!email || !password || users.email !== email || users.password !== password)
return res.status(401).json(success: false, message: "Incorrect username or password")
//use the payload to store information about the user such as username, user role, etc.
let payload = email: email
//create the access token with the shorter lifespan
let accessToken = jwt.sign(payload, process.env.ACCESS_TOKEN_SECRET,
algorithm: "HS256",
expiresIn: process.env.ACCESS_TOKEN_LIFE
)
//create the refresh token with the longer lifespan
let refreshToken = jwt.sign(payload, process.env.REFRESH_TOKEN_SECRET,
algorithm: "HS256",
expiresIn: process.env.REFRESH_TOKEN_LIFE
)
//store the refresh token in the user array
users.refreshToken = refreshToken
//send the access token to the client inside a cookie
// res.cookie("jwt", accessToken, httpOnly: true) //secure: false, use this along with httpOnly: true in production
// res.setHeader('Authorization', accessToken);
res.json(
accessToken: accessToken,
success: true, message: "Authentication success"
);
res.send()
【问题讨论】:
你能说明你在哪里创建令牌以及如何使用环境变量 所以令牌只是过期了。要么只是超出了您设置的时间(故意),要么您错误地设置了到期时间并且到期时间比预期的要早。但是您知道,查看所有细节很重要,稍后在您的代码中,您还可以以不同的方式对不同的异常做出反应。 所以,我登录并在几秒钟后发出请求,但令牌应该持续一个小时! ,您认为这与时区有关吗?我不知道。 @LawrenceCherone 我已经为您更新了问题详情。 当你在jwt.io上解码时,你能显示实际的token还是只显示iat和exp的值? 我刚刚在响应中发送了 process.env.ACCESS_TOKEN_LIFE 的值,它是 "3600" ,也许这是问题所在?然后我在设置过期时间时尝试了parseInt()
,现在我在响应中没有得到状态401,非常感谢!
【参考方案1】:
您遇到的问题似乎是因为您存储超时期限的方式。
来自node-jsonwebtoken 的文档
expiresIn:以秒或描述时间跨度的字符串表示 时间/毫秒。例如:60、“2 天”、“10 小时”、“7 天”。数值被解释 作为秒数。如果您使用字符串,请确保提供时间 单位(天、小时等),否则使用毫秒单位 默认(“120”等于“120ms”)。
因为您存储在您的 process.env 中,所以看起来它正在将其转换为字符串,而不是维护整数值。
测试代码:
const jwt = require('jsonwebtoken')
require('dotenv').config();
let payload = email: 'email'
let accessToken = jwt.sign(payload, process.env.ACCESS_TOKEN_SECRET,
algorithm: "HS256",
expiresIn: process.env.ACCESS_TOKEN_LIFE
)
console.log(accessToken);
console.log('waiting 4 seconds');
setTimeout(function()
let val = jwt.verify(accessToken, process.env.ACCESS_TOKEN_SECRET);
console.log(val);
, 4000);
使用以下 process.env 值,它会失败
ACCESS_TOKEN_SECRET=swsh23hjddnns
ACCESS_TOKEN_LIFE=3600
REFRESH_TOKEN_SECRET=dhw782wujnd99ahmmakhanjkajikhiwn2n
REFRESH_TOKEN_LIFE=86400
但是如果我们将 ACCESS_TOKEN_LIFE 更改为
ACCESS_TOKEN_LIFE=3600S
成功了
如果没有时间单位,任何延迟超过 3.6 秒的请求都会出错。
【讨论】:
以上是关于验证时 JWT 令牌始终无效的主要内容,如果未能解决你的问题,请参考以下文章
JWT 给 JsonWebTokenError “无效令牌”
Laravel JWT 令牌在身份验证 JWT 方法中刷新后无效