使用 JWT 保护 Express 路由

时间:2021-05-06 12:03:22

标签: node.js express jwt authorization

我是 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');
    }
}

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

1 个答案:

答案 0 :(得分:0)

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

<块引用>

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

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

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