【问题标题】:Node Js - Express - CSURF : "invalid csrf token"节点 Js - Express - CSURF:“无效的 csrf 令牌”
【发布时间】:2021-06-19 12:22:00
【问题描述】:

我正在尝试在 firebase 中托管的快速应用程序中实现 csurf,但在一个特定情况下我面临“EBADCSRFTOKEN”错误。 仅当用户通过会话 cookie 登录时才会出现此错误。

我正在使用 JQUERY 发送我的联系表数据。 当没有用户登录时,它可以完美运行。

显示联系表格的路线

router.get('/contact', async(req, res, next) => { 
  try {
    let user = await RequestHelper.checkSessionCookie(req);
    let data = {
      csrfToken: req.csrfToken()
    };
    if (user) { 
      data.customer = await UserController.getUser(user.uid);
    }
    return res.render('contact', data);
  } catch(error) {
    next(error);
  }
});

联系表单中的 Ajax 请求

let csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');    
let data = {...}
$.ajax({
  type: "post",
  data: data,
  headers: {
      'csrf-token': csrfToken
  }, 
  url: "/contactForm",
  success: function(code) {
    window.location.href = '/contacted';
  },error:  function (error) {
    console.log(error);
  }
});

处理表单数据的路由

由于您无需登录即可访问此路由,因此我不调用会话中间件。

router.post('/contactForm', async(req, res) => {
  console.log("CSRF OK !");
});

服务器代码

const functions             = require('firebase-functions');
const admin                 = require('firebase-admin');
const path                  = require('path');
const favicon               = require('express-favicon');
const express               = require('express');
const cookieParser          = require('cookie-parser')();
const csurf                 = require('csurf');
const cors                  = require('cors')({origin: true});

admin.initializeApp();

const app                   = express();

app.set('view engine', 'pug');
app.set('views', config.template.directory);

app.use(favicon(path.join(__dirname, '../public', 'favicon.ico')));
app.use(cors);

app.use('/',              require('./routes/webhooks'));

app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(cookieParser);
app.use(csurf({cookie: { httpOnly: true }}));

app.use('/',              require('./routes/routes'));
app.use('/my',            require('./routes/user'));
app.use('/courses',       require('./routes/courses'));

//CSRF ERROR
app.use((error, req, res, next) => {
  if (error.code === 'EBADCSRFTOKEN') {
    console.log(error);
    console.log(req.get("csrf-token")); // <- displays the token perfectly 
    return res.status(403).send();
  } 
  return next(error);
});

创建会话 cookie 的路由

router.post('/sessionLogin', (req, res, next) => {
  const idToken = req.body.idToken;
  const expiresIn = 60 * 60 * 24 * 5 * 1000;
  
  return admin.auth().createSessionCookie(idToken, { expiresIn }).then((sessionCookie) => {
    const options = { maxAge: expiresIn, httpOnly: true, secure: true };
    res.cookie('__session', sessionCookie, options);
    let response = { 
      status: 'success'
    }
    return res.end(JSON.stringify(response));
  },(error) => {
    console.log(error);
    return res.status(401).send();
  });  
});

即使使用我自己的自定义函数来检查令牌,问题也是一样的

app.use(csurf({ cookie: true, value: (req) => {
  console.log(" ------- CHECK CSRF TOKEN ------- ");
  console.log(req.get("csrf-token"));
  return req.get("csrf-token");
}}));

>   ------- CHECK CSRF TOKEN ------- 
>  6wXhahio-AN2f3zlHJPNShNv1KUAB6tOWN3U
>  ForbiddenError: invalid csrf token

感谢您的帮助。

【问题讨论】:

    标签: jquery node.js firebase express csrf


    【解决方案1】:

    我尝试设置相同的 cookie 名称,用于存储与 firebase 的会话,它似乎有效。

    app.use(csurf({ cookie: { key: "__session", httpOnly: true }));
    

    来自 firebase 文档:

    将 Firebase 托管与 Cloud Functions 或 Cloud Run 一起使用时,cookie 通常会从传入的请求中去除。这对于允许有效的 CDN 缓存行为是必要的。只有特别命名的 __session cookie 被允许传递到您的应用程序的执行中。

    【讨论】:

      猜你喜欢
      • 2017-06-05
      • 2016-02-24
      • 2014-08-26
      • 2020-07-09
      • 2017-01-08
      • 2015-08-24
      • 2021-11-25
      • 2018-03-24
      • 2021-01-02
      相关资源
      最近更新 更多