在哪里控制 expireIn JWT

Posted

技术标签:

【中文标题】在哪里控制 expireIn JWT【英文标题】:Where to control the expireIn JWT 【发布时间】:2017-10-14 17:05:19 【问题描述】:

我正在使用 android、nodeJS 和 postgreSQL(sequelize) 构建客户端-服务器应用程序,我已经能够进行简单的登录和注册,但我想保存会话,所以我这样做了:

router.post('/login', function (req, res, next) 
if (JSON.stringify(req.body) == "") 
    return res.status(400).json( Error: "Login request body is empty" );

if (!req.body.username || !req.body.password) 
    return res.status(400).json( Error: "Missing fields for login" );


// search a user to login
User.findOne( where:  username: req.body.username  ) // searching a user with the same username and password sended in req.body
    .then(function (user) 
        if (user && user.validPassword(req.body.password)) 
            //return res.status(200).json( message: "loged in!" ); // username and password match


            var payload =  user: user ;

            // create a token
            var token = jwt.sign(payload, 'superSecret', 
                expiresIn: 60 * 60 * 24
            );


            // return the information including token as JSON
            res.json(
                success: true,
                message: 'Enjoy your token!',
                token: token
            );

        
        else 
            return res.status(401).json( message: "Unauthorized" ); // if there is no user with specific fields send
        
    ).catch(function (err) 
        console.error(err.stack)
        return res.status(500).json( message: "server issues when trying to login!" ); // server problems
    );

);

正如你们所看到的,当登录成功时,我将令牌返回给客户端,在客户端,我将令牌保存在 SharedPreferences 上。

我的问题是token有过期时间,那么如何控制token的过期时间,应该在服务器端控制,还是在客户端控制呢?

任何提示都是有用的。 谢谢

【问题讨论】:

【参考方案1】:

首先,使用Token方法和Session方法是不一样的。令牌在客户端提供,因此您可以将其发送到服务器端并验证令牌是否已过期。

因此,您可以在服务器端执行类似操作来检查令牌是否仍然可用或已过期。

jwt.verify(token, 'shhhhh', function(err, decoded) 
  if (err) 
    /*
        err = 
        name: 'TokenExpiredError',
        message: 'jwt expired',
        expiredAt: 1408621000
      
    */
  
);

Source here

对于登录,您的代码是正确的,但是一旦用户拥有过期日期的令牌,在每个请求中您必须询问令牌是否有效且未过期。因此,首先您登录用户,然后在每个请求中询问用户令牌是否为有效令牌。

例如:

router.get('/posts', function(req, res)
    // here you verify the token
    // if (err)
    // return err, show login to the user
    // else, get all post from database and return the data to the user  
)

但是,如果您创建一个可以在您从客户端发出的每个私人请求中使用的函数会更好。

function validateToken(token)
    jwt.verify(token, 'shhhhh', function(err, decoded) 
       if (err) 
        /*
            err = 
            name: 'TokenExpiredError',
            message: 'jwt expired',
            expiredAt: 1408621000
          
        */
      

使用私有请求并在发出请求之前验证令牌的示例(如果 validateToken 返回 true,它将转到函数,否则,请求将在该点中断):

 router.get('/posts', validateToken, function(req, res)
    // get all post from database and return the data to the user
 

【讨论】:

感谢您的回答,我有一个问题,是存储会话还是仅存储 android 应用程序的令牌更好? 我真的不知道你是否可以在 android 中存储会话。但是我确信您可以将令牌存储在 SharedPreferences 中,因为 de app 是唯一可以访问该首选项的应用程序,因此存储令牌是安全的并且易于使用!如果这个答案是正确的,请标记它!! 我将其标记为 asnwer,但例如我是否需要在登录后发出请求以解码我从登录中获得的令牌? 你必须为你向api发出的每个请求创建一个中间件函数,并验证用户是否拥有令牌并且令牌是有效的令牌。如果是这样,请求会转到你的后端控制器,如果它无效,你必须请求用户重新登录! 所以登录后我需要检查那个令牌来获取用户,我需要在那里做另一个请求吗?

以上是关于在哪里控制 expireIn JWT的主要内容,如果未能解决你的问题,请参考以下文章

我需要在哪里使用 JWT?

在哪里存储 JWT 令牌?

JWT应该保存在哪里?

我在哪里可以将 jwt 令牌存储在 localStorage 中?

我们可以在哪里安全地存储 JWT 令牌?

jwt.io 从哪里获取 JWT 令牌的公钥?