【问题标题】:How to refresh CSRF token in Nodejs / Express via AJAX如何通过 AJAX 在 Nodejs / Express 中刷新 CSRF 令牌
【发布时间】:2022-02-16 22:09:52
【问题描述】:

场景:

  1. 我的应用中有一个页面,用户似乎在会话/CSFR 过期后仍保持打开状态并返回
  2. 当他们尝试从该页面提交数据并且会话被拒绝时,我有一个功能可以打开登录模式
  3. 提交时,首先会向服务器发出一个请求以发出新的 CSRF 令牌
  4. 收到该令牌后,它会使用该新令牌,并将其与用户凭据一起发送以生成新会话
  5. 然后他们可以继续他们之前的工作

问题是在第 4 步,由于 CSRF 令牌无效,请求失败。

在服务器端,两条路由如下所示(使用 express、csurf):

    const csrf = require("csurf");
    const csrfProtection = csrf({ cookie: true });
    const passport = require("passport");

 //Issue new ajax csrf login token
    app.get("/ajaxLoginToken", csrfProtection, function (req, res) {
       const csrfToken = req.csrfToken();
       res.json({ csrfToken });
       console.log("New csrf token issued", csrfToken);
    });
    
    //AJAX login
    app.post("/ajaxLogin", csrfProtection, function (req, res, next) {
       passport.authenticate("local", async function (err, user, info) {
          //This point is never reached due to csrf mismatch

在浏览器上,步骤 3 如下所示:

async requestNewToken() {
   let response = await fetch("/ajaxLoginToken", {
      method: "GET",
   }); 
   let responseBody = await response.json();
   //Update csrf token
   document.querySelector('meta[name="csrf-token"]').setAttribute("content", responseBody.csrfToken);
   document.cookie = `_csrf=${responseBody.csrfToken}`;

然后发送步骤4,它在发送之前将csrf令牌添加到请求中

async login({email, password}) { 
   let response = await fetch(request.url, {
         method: "POST",
         headers: { 
               "Content-Type": "application/json",
               Accept: "application/json",
               "X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').getAttribute("content")
         },
         body: JSON.stringify({email, password}),
   
         //this always fails due to csrf token

当我尝试调试时,在登录请求中收到了新令牌,但它被拒绝了。任何帮助都会很棒 - 我已经为此苦恼了好几天。

【问题讨论】:

    标签: node.js ajax express csrf csrf-token


    【解决方案1】:

    很难说没有最小的运行示例,但我猜你没有包含 CSRF cookie。通过使用csurf({ cookie: true }) 调用csurf,您决定以cookie 的形式在客户端维护CSRF 令牌,默认情况下称为_csrf。你已经做到了。这种机制称为Double Submit Cookie

    到目前为止,您必须在每个请求中发送两次 CSRF 令牌:作为 Header 或请求参数,取决于您如何配置它,请参阅 csurf - value 了解默认值,AND以 cookie 的形式。据我所知,您永远不会在 AJAX 请求中发送 cookie。您将 CSRF 令牌作为 Header X-CSRF-Token 发送,但您也必须包含 cookie。

    只是一个猜测,但您是否有可能必须使用 credentials 选项来配置您的 fetch 调用?默认情况下,fetch 不包括 cookie。您必须使用credentials: "include" 包含它们。请注意,只有配置了Access-Control-Allow-Origin 标头才能使用credentials: "include",使用include 时不能使用通配符。

    总而言之,我猜你从来没有在你的 AJAX 调用中发送 cookie,你必须配置它。

    【讨论】:

      猜你喜欢
      • 2015-03-24
      • 2016-02-08
      • 2014-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-02
      • 2017-03-14
      • 2012-02-01
      相关资源
      最近更新 更多