【发布时间】:2021-02-28 08:07:03
【问题描述】:
这是我第一次实现 CSRF,也是第一次在 Stack 上发帖。我一直在努力通过 CSRF 配置,但终于得到了几乎可以工作的东西。
如果我在新浏览器中打开带有书签的页面并提交表单,我会看到 403 Invalid CSRF 错误:EBADCSRFTOKEN。在这种情况下,用户身份验证是 cookie,因此它不会挑战。我想知道会话是否已过期?后续帖子工作正常。获取请求都很好。我很困惑,是时候把这个挑战放在一边并寻求帮助,因为我已经做了太久了,不胜感激。
Server.js 不引用 csrf 中间件但建立会话
const express = require("express");
const path = require("path");
const favicon = require("serve-favicon");
const cookieParser = require("cookie-parser");
const bodyParser = require("body-parser");
const flash = require("connect-flash");
const mongoose = require("mongoose");
const logger = require("morgan");
const expressSession = require("express-session");
const setCurrentUser = require("./app/controllers/setCurrentUser");
var session = {
secret: "XXXHIDDENXXX",
cookie: {},
resave: false,
saveUninitialized: false,
};
app.use(favicon(path.join(__dirname, "public/images", "favicon.png")));
app.use(logger("dev"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(flash());
app.use(expressSession(session));
app.use("/public", express.static("public"));
app.use(setCurrentUser);
app.use((req, res, next) => {
res.locals.user = req.user;
res.locals.success = req.flash("success");
res.locals.error = req.flash("error");
next();
});
索引.js
"use strict";
var express = require("express");
var router = express.Router();
const csrf = require("csurf");
const isLoggedIn = require("../controllers/auth");
var csrfProtection = csrf({ cookie: true });
router.use(csrf({ cookie: true }));
router.use((req, res, next) => {
// generate one CSRF token to every render page
res.locals.token = req.csrfToken();
next();
});
router.get("/settings", isLoggedIn, csrfProtection, function (req, res, next) {
...
});
router.post("/settings", isLoggedIn, csrfProtection, function (req, res, next) {
...
});
接口,我用的是EJS,相关代码:
<head>
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="<%= locals.token %>">
</head>
<form method="POST" action="/settings">
<input type="hidden" name="_csrf" value="<%= locals.token %>">
<div class="form-group">
<label for="displayName">Name</label>
<input type="text" name="displayName" id="displayName" maxlength='30' data-parsley-maxlength='30' class="form-control" value="<%= user.displayName %>" required>
</div>
<button class="btn btn-primary">Submit</button>
</form>
以上代码按预期呈现:
<meta name="csrf-param" content="authenticity_token">
<meta name="csrf-token" content="qBdXd2ZQ-8vnbyw_IUivar_6UKp0qvhUf290">
<input type="hidden" name="_csrf" value="qBdXd2ZQ-8vnbyw_IUivar_6UKp0qvhUf290">
令牌通过 post 数据中的表单 post 发送为 _csrf: qBdXd2ZQ-8vnbyw_IUivar_6UKp0qvhUf290
【问题讨论】:
-
无关提示:您正确使用了
const,所以也要使用let(而不是var)。
标签: javascript node.js express csrf