【发布时间】: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