Nodejs express 4中ejs表单csrf的值为undefined,求大神给提示

Nodejs express 4中ejs表单csrf的值为undefined,求大神给提示

包
{
“name”: “biizhi”,
“version”: “0.0.1”,
“private”: true,
“scripts”: {
“start”: “node ./bin/www”
},
“dependencies”: {
“express”: “~4.2.0”,
“static-favicon”: “~1.0.0”,
“morgan”: “~1.0.0”,
“cookie-parser”: “~1.0.1”,
“body-parser”: “~1.0.0”,
“connect-mongo”: “^0.4.0”,
“mongoose”: “~2.8.0”,
“debug”: “~0.7.4”,
“cheerio”:"",
“request”: "",
“ejs”: “~0.8.5”,
“express-session”: “~1.6.3”,
“validator”:"~3.16.0",
“xss”:"~0.1.9",
“csurf”:"~1.3.0"
}
}
以下为APP.JS
app.use(favicon());
app.use(logger(‘dev’));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(session({
resave:true,
saveUninitialized:true,
key: ‘sid’,
secret: settings.cookieSecret,
store: new MongoStore({
db: settings.db
})
}));
app.use(csrf());
app.use(function(req, res, next){
res.locals.csrf = req.session ? req.session._csrf : “”;
next();
});
app.use(express.static(path.join(__dirname, ‘public’)));

ejs表单中 <form> <input type=‘hidden’ name=’_csrf’ value=’<%= csrf %>’ /> </form>

报错: invalid csrf token

403

Error: invalid csrf token at createToken (D:\Workspaces\HTML5\biizhi\node_modules\csurf\index.js:107:19) at Layer.handle (D:\Workspaces\HTML5\biizhi\node_modules\csurf\index.js:67:24) at trim_prefix (D:\Workspaces\HTML5\biizhi\node_modules\express\lib\router\index.js:240:15) at D:\Workspaces\HTML5\biizhi\node_modules\express\lib\router\index.js:208:9 at Function.proto.process_params (D:\Workspaces\HTML5\biizhi\node_modules\express\lib\router\index.js:269:12) at next (D:\Workspaces\HTML5\biizhi\node_modules\express\lib\router\index.js:199:19) at D:\Workspaces\HTML5\biizhi\node_modules\express-session\index.js:285:9 at D:\Workspaces\HTML5\biizhi\node_modules\connect-mongo\lib\connect-mongo.js:222:17 at D:\Workspaces\HTML5\biizhi\node_modules\connect-mongo\node_modules\mongodb\lib\mongodb\collection\query.js:147:5 at Cursor.nextObject (D:\Workspaces\HTML5\biizhi\node_modules\connect-mongo\node_modules\mongodb\lib\mongodb\cursor.js:733:5)

控制台结果: _csrf:undefined

求大神给个提示啊


8 回复

针对您遇到的问题,_csrf 的值为 undefined,这通常意味着 CSRF 中间件没有正确地设置 _csrf 值。我们可以检查几个关键点来解决这个问题。

1. 确认中间件顺序

确保 app.use(csrf());app.use(express.static(...)); 之前调用。这是因为静态文件中间件需要在 CSRF 中间件之后运行,以确保能够正确地注入 CSRF 令牌。

2. 设置 CSRF 令牌

确保 CSRF 令牌被正确地注入到请求的 req 对象中。csurf 中间件会自动将 CSRF 令牌添加到 req.csrfToken() 方法中。我们需要更新中间件函数以正确获取 CSRF 令牌:

app.use(function(req, res, next) {
    res.locals.csrf_token = req.csrfToken(); // 使用 req.csrfToken() 获取 CSRF 令牌
    next();
});

3. 更新 EJS 表单

确保在 EJS 模板中正确使用 CSRF 令牌:

<form method="POST" action="/your-endpoint">
    <input type="hidden" name="_csrf" value="<%= csrf_token %>">
    <!-- 其他表单字段 -->
</form>

4. 验证 CSRF 令牌

确保您的后端路由验证 CSRF 令牌。csurf 中间件会在每个 POST 请求中自动检查 CSRF 令牌的有效性。

示例代码

app.js

const express = require('express');
const session = require('express-session');
const cookieParser = require('cookie-parser');
const csrf = require('csurf');

const app = express();

// 设置中间件
app.use(cookieParser());
app.use(session({
    resave: true,
    saveUninitialized: true,
    key: 'sid',
    secret: 'your-secret-key',
    store: new MongoStore({ db: 'your-db-name' })
}));

app.use(csrf());

app.use((req, res, next) => {
    res.locals.csrf_token = req.csrfToken(); // 注入 CSRF 令牌
    next();
});

app.use(express.static(path.join(__dirname, 'public')));

// 路由
app.post('/your-endpoint', (req, res) => {
    // 处理表单提交
    console.log(req.body);
    res.send('Form submitted successfully');
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

通过这些步骤,您可以确保 CSRF 令牌正确地生成并在 EJS 表单中使用。希望这能解决您的问题!


res.locals.token = req.csrfToken();

app.use(function(req, res, next){ res.locals.csrf = req.session ? req.session._csrf : “”; res.locals.token = req.csrfToken();//加在这里吗? next(); });

结果还是一样,前台标签中_csrf 的值还是 undefined

app.use(function(req, res, next){ console.log(req.session);//查下中间件位置。我刚没看中间件。 res.locals.csrf = req.session ? req.session._csrf : “”; next(); });

你上面的代码赋值的 local 变量是 token,但你要取 _csrf… 要不你去看看我们 cnode 是怎么解决这个问题的?

session有的。

根据你的描述,问题可能出在 res.locals.csrf 的赋值方式。在 Express 4 中,CSRF 令牌是由中间件 csurf 自动生成并存储在 req.csrfToken() 方法中的。因此,你需要确保正确地将 CSRF 令牌传递到 EJS 模板。

以下是修正后的代码示例:

app.js

const express = require('express');
const session = require('express-session');
const csurf = require('csurf');
const cookieParser = require('cookie-parser');

const app = express();

app.use(cookieParser()); // 确保先使用 cookieParser 中间件
app.use(session({
  resave: true,
  saveUninitialized: true,
  key: 'sid',
  secret: 'your_secret_key',
  store: new MongoStore({ db: 'your_db_name' })
}));

app.use(csurf());

// 将 CSRF 令牌添加到视图
app.use((req, res, next) => {
  res.locals.csrftoken = req.csrfToken(); // 使用 req.csrfToken() 获取 CSRF 令牌
  next();
});

app.set('view engine', 'ejs');

// 其他中间件和路由配置

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ejs 表单

<form action="/submit" method="POST">
  <input type="hidden" name="_csrf" value="<%= csrftoken %>" />
  <!-- 其他表单字段 -->
  <button type="submit">Submit</button>
</form>

解释

  1. cookieParser: 需要在 sessioncsurf 之前使用。
  2. req.csrfToken(): 用于获取 CSRF 令牌,并将其存储在 res.locals.csrftoken 中。
  3. EJS 表单: 使用 <%= csrftoken %> 来插入 CSRF 令牌。

通过这种方式,你可以确保 CSRF 令牌正确地传递到 EJS 模板,并且在表单提交时能够正确验证。

回到顶部