使用 JWT 保护 Express 路由

Securing Express route with JWT

我是 JWT 身份验证的新手,我需要保护 Express 路由。在添加身份验证之前,我使用 Express 对 return 一个 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 代码的消息。有没有办法让它表现得像我添加授权之前一样?

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

AJAX stands for Asynchronous JavaScript And XML. In a nutshell, it is the use of the XMLHttpRequest object to communicate with servers. It can send and receive information in various formats, including JSON, XML, HTML, and text files. AJAX’s most appealing characteristic is its "asynchronous" nature, which means it can communicate with the server, exchange data, and update the page without refreshing the page. _From MDN WebDocs Ajax/Getting Started

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

上找到 JWT

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

获取 JWT 令牌