Csurf 禁止错误:在 Node.js 中 csrfToken 代码无效:’EBADCSRFTOKEN’。

huangapple go评论80阅读模式
英文:

Csurf Forbidden Error: invalid csrfToken code: 'EBADCSRFTOKEN' in nodejs

问题

在我的博客项目中,CSRF 在一些 POST 路由上正常工作,比如登录、注册、注销、更新帐户信息等,但在管理员路由中,当我尝试创建/更新帖子或类别时失败并抛出禁止错误。我尝试了许多其他问题中提到的解决方案,但都没有解决我的问题。

require('dotenv').config();

const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const session = require('express-session');
const MongoStore = require('connect-mongo');
const flash = require('connect-flash');
const csrf = require('csurf');

const errorController = require('./controllers/error');
const uri = process.env.URI;
const app = express();
const csrfProtection = csrf();

app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
app.use(
  session({
    secret: 'my secrets',
    saveUninitialized: false,
    resave: false,
    store: MongoStore.create({
      mongoUrl: uri,
      autoRemove: 'native',
      ttl: 7200, //2 hours
      collectionName: 'sessions',
    }),
  })
);
app.use(csrfProtection);
app.use(flash());

app.use((req, res, next) => {
  res.locals.isAuthenticated = req.session.isLoggedIn;
  res.locals.name = undefined;                //
  res.locals.level = 0;                       //
  if (req.session.user) {                     //
    res.locals.name = req.session.user.name;  //those line for render nav bar in views
    res.locals.level = req.session.user.level;//
  }                                           //
  res.locals.csrfToken = req.csrfToken();
  next();
});

// routes
const authRoutes = require('./routes/auth');
const pageRoutes = require('./routes/page');
const adminRoutes = require('./routes/admin');

app.use(pageRoutes);            //
app.use('/auth', authRoutes);   //everything works fine
app.use('/admin', adminRoutes); // errors

// error pages
app.use(errorController.get404);

app.use((error, req, res, next) => {
  console.log(error);
  res.status(500).render('errors/500', {
    pageTitle: '500',
    error: error,
  });
});

mongoose
  .connect(uri)
  .then(result => {
    app.listen(3000);
  })
  .catch(error => console.log(error));

我在每个 POST 表单中都添加了以下输入:

<input type="hidden" name="_csrf" value="<%= csrfToken%>" />

当我将错误日志记录时:

ForbiddenError: invalid csrf token
    at csrf (D:\Tai lieu hoc tap\Code\Personal Projects\Blog\node_modules\csurf\index.js:112:19)
    at Layer.handle [as handle_request] (D:\Tai lieu hoc tap\Code\Personal Projects\Blog\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (D:\Tai lieu hoc tap\Code\Personal Projects\Blog\node_modules\express\lib\router\index.js:328:13)
    at D:\Tai lieu hoc tap\Code\Personal Projects\Blog\node_modules\express\lib\router\index.js:286:9
    at Function.process_params (D:\Tai lieu hoc tap\Code\Personal Projects\Blog\node_modules\express\lib\router\index.js:346:12)      
    at next (D:\Tai lieu hoc tap\Code\Personal Projects\Blog\node_modules\express\lib\router\index.js:280:10)
    at D:\Tai lieu hoc tap\Code\Personal Projects\Blog\node_modules\express-session\index.js:506:7
    at D:\Tai lieu hoc tap\Code\Personal Projects\Blog\node_modules\connect-mongo\build\main\lib\MongoStore.js:221:17
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  code: 'EBADCSRFTOKEN'
}

感谢每一个答案!因为我可以从这里的每个人那里学到一些东西。

英文:

In my blog project, csrf works fine on some post routes like login, register, logout, update account information,... but in the admin routes, when I tried to create/update a post or a category - it failed and threw the forbidden error. I tried many solutions from other questions but nothing worked for me.

require(&#39;dotenv&#39;).config();
const path = require(&#39;path&#39;);
const express = require(&#39;express&#39;);
const bodyParser = require(&#39;body-parser&#39;);
const mongoose = require(&#39;mongoose&#39;);
const session = require(&#39;express-session&#39;);
const MongoStore = require(&#39;connect-mongo&#39;);
const flash = require(&#39;connect-flash&#39;);
const csrf = require(&#39;csurf&#39;);
const errorController = require(&#39;./controllers/error&#39;);
const uri = process.env.URI;
const app = express();
const csrfProtection = csrf();
app.set(&#39;view engine&#39;, &#39;ejs&#39;);
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, &#39;public&#39;)));
app.use(
session({
secret: &#39;my secrets&#39;,
saveUninitialized: false,
resave: false,
store: MongoStore.create({
mongoUrl: uri,
autoRemove: &#39;native&#39;,
ttl: 7200, //2 hours
collectionName: &#39;sessions&#39;,
}),
})
);
app.use(csrfProtection);
app.use(flash());
app.use((req, res, next) =&gt; {
res.locals.isAuthenticated = req.session.isLoggedIn;
res.locals.name = undefined;                //
res.locals.level = 0;                       //
if (req.session.user) {                     //
res.locals.name = req.session.user.name;  //those line for render nav bar in views
res.locals.level = req.session.user.level;//
}                                           //
res.locals.csrfToken = req.csrfToken();
next();
});
// routes
const authRoutes = require(&#39;./routes/auth&#39;);
const pageRoutes = require(&#39;./routes/page&#39;);
const adminRoutes = require(&#39;./routes/admin&#39;);
app.use(pageRoutes);            //
app.use(&#39;/auth&#39;, authRoutes);   //everything works fine
app.use(&#39;/admin&#39;, adminRoutes); // errors
// error pages
app.use(errorController.get404);
app.use((error, req, res, next) =&gt; {
console.log(error);
res.status(500).render(&#39;errors/500&#39;, {
pageTitle: &#39;500&#39;,
error: error,
});
});
mongoose
.connect(uri)
.then(result =&gt; {
app.listen(3000);
})
.catch(error =&gt; console.log(error));

And I have put this input in every post form:

&lt;input type=&quot;hidden&quot; name=&quot;_csrf&quot; value=&quot;&lt;%= csrfToken%&gt;&quot; /&gt;

The error when I logged it out:

ForbiddenError: invalid csrf token
at csrf (D:\Tai lieu hoc tap\Code\Personal Projects\Blog\node_modules\csurf\index.js:112:19)
at Layer.handle [as handle_request] (D:\Tai lieu hoc tap\Code\Personal Projects\Blog\node_modules\express\lib\router\layer.js:95:5)
at trim_prefix (D:\Tai lieu hoc tap\Code\Personal Projects\Blog\node_modules\express\lib\router\index.js:328:13)
at D:\Tai lieu hoc tap\Code\Personal Projects\Blog\node_modules\express\lib\router\index.js:286:9
at Function.process_params (D:\Tai lieu hoc tap\Code\Personal Projects\Blog\node_modules\express\lib\router\index.js:346:12)      
at next (D:\Tai lieu hoc tap\Code\Personal Projects\Blog\node_modules\express\lib\router\index.js:280:10)
at D:\Tai lieu hoc tap\Code\Personal Projects\Blog\node_modules\express-session\index.js:506:7
at D:\Tai lieu hoc tap\Code\Personal Projects\Blog\node_modules\connect-mongo\build\main\lib\MongoStore.js:221:17
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
code: &#39;EBADCSRFTOKEN&#39;
}

Thanks for every answer! Because I can learn something from everyone here.

答案1

得分: 0

问题出在表单标签中的enctype属性。在身份验证路由中只更新文本,因此我使用默认的enctype(application/x-www-form-urlencoded),但在更新帖子或类别时可能会更新新图像,所以我使用了带有multer的多部分enctype。

只需要在表单操作中添加一个查询,名称为_csrf,值为csrfToken。不再有错误。

之前:

<form action="/admin/update-post" method="POST" enctype="multipart/form-data">

之后:

<form action="/admin/update-post?_csrf=<%= csrfToken%>" method="POST" enctype="multipart/form-data">

英文:

The problem here came from enctype in the form tag. While updating in auth routes only about texts so I use default enctype (application/x-www-form-urlencoded), but updating a post or category may update a new image so I use multipart enctype with multer.

Just need to add a query in form action with the name = _csrf, value = csrfToken. No more error.

Before:

&lt;form action=&quot;/admin/update-post&quot; method=&quot;POST&quot; enctype=&quot;multipart/form-data&quot;&gt;

After:

&lt;form action=&quot;/admin/update-post?_csrf=&lt;%= csrfToken%&gt;&quot; method=&quot;POST&quot; enctype=&quot;multipart/form-data&quot;&gt;

huangapple
  • 本文由 发表于 2023年7月24日 15:18:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76752176.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定