使用 JWT 保护 Express 路线

Posted

技术标签:

【中文标题】使用 JWT 保护 Express 路线【英文标题】:Securing Express route with JWT 【发布时间】:2021-07-28 17:53:46 【问题描述】:

我是 JWT 身份验证的新手,我需要保护 Express 路由。在添加身份验证之前,我执行以下操作以使用 Express 返回 html 页面:

var cache = ;

app.get('/my_page', function (req, res) 
    serveStatic(res, cache, './public/default/my_page.html');
);

其中 serveStatic 是:

var send404 = function (response) 
    response.writeHead(404, 'Content-Type': 'text/plain');
    response.write('Error 404: Resource not found.');
    response.end();


var sendFile = function(response, filePath, fileContents) 
    var mimeType = mime.lookup(path.basename(filePath));
    response.writeHead(200, "content-type": mimeType);
    response.end(fileContents);


var serveStatic = function(response, cache, absPath) 
    if (cache[absPath]) 
        sendFile(response, absPath, cache[absPath]);
     else 
        fs.exists(absPath, function(exists) 
            if (exists) 
                fs.readFile(absPath, function(err, data) 
                    if (err) 
                        send404(response);
                     else 
                        cache[absPath] = data; // Cache the file
                        sendFile(response, absPath, data); // Serve the file
                    
                );
             else 
                send404(response);
            
        );
    

用户点击按钮访问页面:<button type="button" onclick="window.location='my_page'">Go</button>

我添加了如下认证:

// In /middleware/auth file
const jwt = require("jsonwebtoken");
const dotenv = require('dotenv');
dotenv.config();

module.exports = function(req, res, next) 
    const token = req.header("Authorization");

    if (!token) 
        return res.status(401).json(
            message: "Auth Error",
            errorCode: 401,
            redirectUrl: "/"
        );
    
    
    try 
        const decoded = jwt.verify(token, process.env.SECRET);
        req.user = decoded.user;
        next();
     catch (e)         
        res.status(500).send(
            message: "Invalid Token",
            errorCode: 500,
            redirectUrl: "/"
        );
    
;

我把路由管理改成:

const auth = require("./middleware/auth");

app.get('/licenses',
    auth,
    function (req, res, next) 
        serveStatic(res, cache, './public/default/my_page.html');
    
);

我更改了 onclick 按钮以调用从 cookie 中检索 JWT 并将其与请求一起发送的函数。

<button type="button" onclick="openPage()">Go</button>
var openPage= function() 
    if (document.cookie != "") 
        var token = getCookie("token");

        if (token != "") 
            $.ajax(
                type: "GET",
                url: "/my_page",
                data: ,
                dataType: "json",
                beforeSend: function (xhr) 
                    xhr.setRequestHeader('Authorization', token); 
                ,
                success: function(msg) 
                    
                ,
                error: function($xhr, textStatus, errorThrown) 
                    
                
            );
         else 
            console.error('token is empty');
        
     else 
        console.error('cookie is empty');
    

身份验证过程很好,但客户端收到一条消息,其中包含 my_page.html 代码在其 responseText 属性中。有没有办法让它表现得像我添加身份验证之前的样子?

【问题讨论】:

【参考方案1】:

我认为问题在于,一开始,您将浏览器重定向到 /my_page 端点。所以浏览器接收整个 HTML 网页作为HTTP 请求的payload 并在页面上呈现。然后,您更改 AJAX 请求的行为,允许在不刷新页面的情况下从服务器获取数据。

AJAX 代表异步 javascript 和 XML。简而言之,就是使用 XMLHttpRequest 对象与服务器进行通信。它可以发送和接收各种格式的信息,包括 JSON、XML、HTML 和文本文件。 AJAX 最吸引人的特点是它的“异步”特性,这意味着它可以与服务器通信、交换数据、更新页面而无需刷新页面。 _来自 MDN WebDocs Ajax/Getting Started

您可能会恢复将客户重定向到您之前所做的方式(尽管最好使用锚标记),但这不会解决您的问题。授权中间件将拒绝请求,因为它在 Authentication 标头上找不到 JWT。

尽管如此,从您对 openPage 函数的实现来看,我看到您已经将 JWT 令牌存储在 cookie 中。 Cookie 与每个请求一起发送到服务器。最好尝试修改身份验证中间件以从 cookie 中获取 JWT 令牌,而不是从 Authentication 标头中获取。

【讨论】:

成功了,谢谢。我像以前一样替换了 AJAX 调用,并从 cookie 中检索了令牌。

以上是关于使用 JWT 保护 Express 路线的主要内容,如果未能解决你的问题,请参考以下文章

JWT 和 express-JWT 有问题

如何使用 JWT 在 Express 中验证单个路由(无代码重复)的多种类型用户的身份验证令牌?

express-jwt 通过路由处理特定的秘密密码

Express + JWT 排除某些路线

使用 express js、passport s 保护 GraphQL 查询

无法使用 passport-jwt 访问受保护的路线