使用刷新令牌进行JWT身份验证

使用刷新令牌进行JWT身份验证

在构建Web应用程序时,身份验证是重要的方面之一,我们通常使用JWT令牌来实现身份验证(您可以在这里了解更多关于JWT的知识)。我们创建一个访问令牌并将其存储在本地存储、会话或Cookie中。但是,使用刷新令牌来实现这一点会更安全。

刷新令牌: 它是用于获取额外访问令牌的唯一令牌。这使您可以拥有短期访问令牌,而无需每次访问令牌过期时都要收集凭据。

由于出于安全原因,访问令牌的有效期不会很长,刷新令牌可用于重新验证用户而无需登录凭据。即使我们的访问令牌被破坏,刷新令牌也不会暴露给客户端JavaScript,它将在非常短的时间内过期。因此,我们将发送两个令牌而不是一个,一个是访问令牌,一个是刷新令牌。访问令牌将包含所有用户信息,并将存储在JavaScript运行时中,但刷新令牌将安全地存储在HTTP-only Cookie中。

使用刷新令牌进行JWT身份验证

认证持久性: 我们可以在刷新和登录之间轻松持久化用户,而无需任何凭据。我们可以创建一个名为“refresh”的新路由,当令牌过期或用户刷新时,我们可以通过向此路由发送请求来获取新的访问令牌。

使用刷新令牌进行JWT身份验证

实现: 现在让我们使用JWT和刷新令牌来实现身份验证。我们将首先创建一个新的Express应用程序并安装所有必需的依赖项。

步骤1: 运行以下命令来初始化项目并创建一个索引文件和env文件。(确保你已经安装了node和npm)

npm init -y
JavaScript
touch index.js .env
JavaScript

步骤2: 安装所有必需的依赖项并在代码编辑器中打开项目。

npm install express cookie-parser dotenv jsonwebtoken 
JavaScript

项目结构:

使用刷新令牌进行JWT身份验证

我们将在Index.js中编写我们的身份验证逻辑。首先,我们将创建一个express应用程序,然后实现两个路由 登录刷新 。登录路由将收到一个post请求,然后它将检查凭据是否匹配,如果匹配则会在响应中发送一个刷新令牌和访问令牌。刷新路由也会收到一个post请求,它将验证刷新令牌,如果正确,则会用新的访问令牌进行响应,否则会抛出授权错误。

示例: 现在我们将实现两个路由登录和刷新。下面的代码是index.js:

文件名:index.js

const dotenv = require('dotenv'); 
const express = require('express'); 
const cookieparser = require('cookie-parser'); 
const jwt = require('jsonwebtoken') 
const bodyParser = require('body-parser'); 
  
// Configuring dotenv 
dotenv.config(); 
  
const app = express(); 
  
// Setting up middlewares to parse request body and cookies 
app.use(express.json()); 
app.use(express.urlencoded({ extended: false })); 
app.use(cookieparser()); 
  
const userCredentials = { 
    username: 'admin', 
    password: 'admin123', 
    email: 'admin@gmail.com'
} 
  
app.post('/login', (req, res) => { 
    // Destructuring username & password from body 
    const { username, password } = req.body; 
  
    // Checking if credentials match 
    if (username === userCredentials.username &&  
        password === userCredentials.password) { 
          
        //creating a access token 
        const accessToken = jwt.sign({ 
            username: userCredentials.username, 
            email: userCredentials.email 
        }, process.env.ACCESS_TOKEN_SECRET, { 
            expiresIn: '10m'
        }); 
        // Creating refresh token not that expiry of refresh  
        //token is greater than the access token 
          
        const refreshToken = jwt.sign({ 
            username: userCredentials.username, 
        }, process.env.REFRESH_TOKEN_SECRET, { expiresIn: '1d' }); 
  
        // Assigning refresh token in http-only cookie  
        res.cookie('jwt', refreshToken, { httpOnly: true,  
            sameSite: 'None', secure: true,  
            maxAge: 24 * 60 * 60 * 1000 }); 
        return res.json({ accessToken }); 
    } 
    else { 
        // Return unauthorized error if credentials don't match 
        return res.status(406).json({  
            message: 'Invalid credentials' }); 
    } 
}) 
  
app.post('/refresh', (req, res) => { 
    if (req.cookies?.jwt) { 
  
        // Destructuring refreshToken from cookie 
        const refreshToken = req.cookies.jwt; 
  
        // Verifying refresh token 
        jwt.verify(refreshToken, process.env.REFRESH_TOKEN_SECRET,  
        (err, decoded) => { 
            if (err) { 
  
                // Wrong Refesh Token 
                return res.status(406).json({ message: 'Unauthorized' }); 
            } 
            else { 
                // Correct token we send a new access token 
                const accessToken = jwt.sign({ 
                    username: userCredentials.username, 
                    email: userCredentials.email 
                }, process.env.ACCESS_TOKEN_SECRET, { 
                    expiresIn: '10m' 
                }); 
                return res.json({ accessToken }); 
            } 
        }) 
    } else { 
        return res.status(406).json({ message: 'Unauthorized' }); 
    } 
}) 
  
app.listen(process.env.PORT, () => { 
    console.log(`Server active on http://localhost:${process.env.PORT}!`); 
})
JavaScript
  • .env: 下面的代码是用来存储敏感凭证,例如API密钥的.env文件:
PORT = 5000 
ACCESS_TOKEN_SECRET=MYSECRETACCESS 
REFRESH_TOKEN_SECRET=MYREFRESHTOKENSECRET 
JavaScript

输出:

使用刷新令牌进行JWT身份验证

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

登录

注册