验证后,JWT令牌始终无效

时间:2020-10-29 15:17:34

标签: node.js express jwt

我是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)

我在哪里错了?

编辑:

我在console.log(e)内的verify函数中添加了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) 在export.verify(/home/shashank/Documents/sms/server/controllers/auth.js:62:23) 在Layer.handle [作为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) {expiredAt: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()

}

1 个答案:

答案 0 :(得分:1)

您似乎遇到的问题是由于您如何存储超时期限。

摘自node-jsonwebtoken的文档

expiresIn:以秒或描述时间跨度的字符串表示 时代/毫秒。例如:60,“ 2天”,“ 10h”,“ 7d”。数值被解释 以秒为单位。如果您使用字符串,请确保您提供时间 单位(天,小时等),否则将使用毫秒单位 默认值(“ 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秒的请求都会出错。