如何在带有 AJAX 的客户端中使用 JWT

Posted

技术标签:

【中文标题】如何在带有 AJAX 的客户端中使用 JWT【英文标题】:How to use JWT in Client with AJAX 【发布时间】:2018-11-22 15:09:31 【问题描述】:

我的应用程序是一个 Node.js API,在同一个应用程序内有一个客户端。

我正在尝试实现一个简单的身份验证登录,它使用由 Node.js API 生成的 JWT 令牌

我的逻辑如下:

    客户端:用户向/auth/login路由提交登录信息。
     $.ajax(
        url: "/auth/login",
        type: "POST",
        data: formData,
        dataType: "json",
        success: function(data, textStatus, jqXHR) 
            if (typeof data.redirect == "string") 
                window.location = data.redirect; 
            
        ,
        error: function(data) 
            if (typeof fail === "function") fail(data);
        
    );
    API:验证用户并在成功时生成 JWT 并发回给客户端。
router.post("/login", async (req, res) => 

    var login =  UID: req.body.UID, password: req.body.password ;
    AU.manualLogin(login)
        .then(result => 

            res.header("x-auth-token", result.token).json(
                status: 200,
                message: "success",
                data: result.data,
                redirect: "/dashboard" 
            );

        )
        .catch(err => next( status: 400, message: err.message ));
);

    客户端:将 JWT 保存到标头并检查 redirect - 在这种情况下,我在成功登录后使用 window.location 指向 /dashboard。 (这部分我不确定)

    API:中间件检查受保护路由上的有效 JWT。

module.exports = function auth(req, res, next) 

    const token = req.headers["x-auth-token"];
    if (!token)
        return res.status(401).send("Access denied. No token provided.");

    try 
        const decoded = jwt.verify(token, "jwtPrivateKey");
        req.user = decoded;
        next(); //pass control to next middleware
     catch (ex) 
        res.status(400).send("Invalid token.");
    
;

问题:

令牌肯定是从 API -> 客户端发送的。但我不知道如何从客户端处理令牌。我认为问题可能与 window.location 重定向有关,因为此时它似乎没有将 x-auth-token 发送到 API。

我的尝试

我已经使用 Postman 从端到端测试了该解决方案,它运行良好。这可能证明问题不在于 API 方面。

我也试过这些来源:

Pass request headers in a jQuery AJAX GET call

Adding custom header in HTTP before redirect

How to add header to request in Jquery Ajax?

jwt on node - how does the client pass the token back to the server

【问题讨论】:

我建议在重定向之前,将令牌保存在本地存储或 cookie 中 @DarkLord 我从多个来源听说保存到本地存储或 cookie 不是一个好主意,但我还是很陌生。甚至可以在没有本地存储和 cookie 的情况下完成吗? 【参考方案1】:

您需要某种存储来保存令牌。否则,用户必须在关闭浏览器/选项卡后再次登录。因此,将令牌保存在 本地会话存储 中是很常见的。

方法 1:使用 Angular、vue.js、react 等单页应用程序 (SPA) 框架来保护您的客户端路由

方法 2:您只能从后端请求 html 和 css(视图),然后在登录过程后存储令牌。使用有效令牌,通过 ajax 请求获取(受保护的)数据。如果 ajax 请求返回状态码 401(未授权)或用户想要访问受保护的路由而不存储令牌,则重定向到登录页面。这也许是最适合你的。

方法 3:将 Node.js 与 express 等后端框架一起使用,并将身份验证信息存储在服务器端会话中

index.js

const express = require('express');
const session = require('express-session');
const app = express();
app.use(require("cookie-parser")());
app.use(session( secret: 'aslwezoweasdfasdlkfalksdfhweelaerfcv', resave: false, saveUninitialized: true));

routes/protectedRoutes.js

const express = require('express');
const router = express.Router();
router.all("/*", util.handleAuthenticate); // check auth on every request
// other routes

indexController.js(登录功能)

module.exports.login = function(req, res) 
    if(!req.session.name) 
        // check username/password --> db lookup
        // if valid:
        req.session.name  = ...
        // redirect to home or backref
        // else: redirect to login
    

util/security.js

function isLoggedIn(req) 
    return !!req.session.name;


function handleAuthenticate(req, res, next) 
    if(isLoggedIn(req))
    
        next();
    
    else
    
    // redirect to login page
    

【讨论】:

如何将该代码用于第 1 号(上图)的初始请求中?之后我尝试添加此内容,但没有成功。

以上是关于如何在带有 AJAX 的客户端中使用 JWT的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 JWT Auth/Laravel 的 Angular JS 获取新的刷新令牌后,如何恢复/重新发送请求?

带有 jQ​​uery Ajax 的 JWT 令牌

如何在前端的 Javascript Ajax API 调用中隐藏我的 JWT 令牌?

如何在 Angular 中从服务器获取带有 jwt 令牌的响应标头

如何在前端和后端存储 JWT 刷新令牌?

如何在身份验证中使用 JWT?