I get "ForbiddenError: invalid csrf token" when I try to use {cookie: { secure: true }} session configuration. How do I implement this?

I get "ForbiddenError: invalid csrf token" when I try to use {cookie: { secure: true }} session configuration. How do I implement this?

我不明白为什么这不起作用。我在单击登录时收到此“ForbiddenError:无效的 csrf 令牌”消息,但我读到必须在会话中启用 {cookie: {httpOnly: true, secure: true}} 选项才能获得相对安全的应用程序 运行(我使用JWT,我是会话和 cookie 方面的新手)

这是我的文件:

app.js

 // ____ Imports ____
    const path = require('path');
    const express = require('express');
    const bodyParser = require('body-parser');
    const sessionConfig = require('./middleware/sessions');
    const userProvider = require('./middleware/userProvider');
    const connectDB = require('./services/db');
    const csrf = require('csurf');
     
    // ____ Middlewares ____
    const app = express();
    const csrfProtection = csrf();
    app.set('view engine', 'ejs');
    app.set('views', 'views');
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(express.static(path.join(__dirname, 'public')));
    app.use(sessionConfig);
    app.use(userProvider);
    app.use(csrfProtection);
    app.use((req, res, next) => {
      res.locals.isAuth = req.session.isAuth;
      res.locals.csrfToken = req.csrfToken();
      next();
    });
     
    // ____ Routes ____
    const adminRoutes = require('./routes/admin');
    const shopRoutes = require('./routes/shop');
    const authRoutes = require('./routes/auth');
    const errorController = require('./controllers/error');
    app.use('/admin', adminRoutes);
    app.use(shopRoutes);
    app.use(authRoutes);
    app.use(errorController.get404);
     
    // ____ Database & Server spin-up ____
    const PORT = process.env.PORT || 3000; //deployment looks for process.env.PORT
    connectDB(() => {
      app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
    });

./middleware/sessions.js

const session = require('express-session');
const MongoDBStore = require('connect-mongodb-session')(session);
const config = require('config');
 
const store = new MongoDBStore({
  uri: config.get('mongoURI'),
  collection: 'sessions',
});
 
const sessionConfig = session({
  secret: config.get('sessionSecret'),
  resave: false,
  saveUninitialized: false,
  store: store,
  cookie: { httpOnly: true, secure: true },
});
 
module.exports = sessionConfig;

./middleware/isAuth.js

module.exports = (req, res, next) => {
  if (!req.session.isAuth) {
    return res.redirect('/login');
  }
  next();
};

./middleware/userProvider.js

 const User = require('../models/user');
     
    module.exports = async (req, res, next) => {
      try {
        if (!req.session.user) {
          return next();
        }
        let user = await User.findById(req.session.user._id);
        req.user = user;
        next();
      } catch (error) {
        console.log(error);
      }
    };

postLogin控制器(通过isAuth中间件)

    exports.postLogin = async (req, res) => {
  try {
    let { email, password } = req.body;
    let user = await User.findOne({ email: email });
    let doMatch = await bcrypt.compare(password, user.password);
    if (doMatch) {
      console.log('Match!');
      //use .save() method to make sure it redirects only when session is already created
      req.session.user = user;
      req.session.isAuth = true;
      return req.session.save(() => {
        res.redirect('/');
      });
    } else {
      return res.redirect('/login');
    }
  } catch (error) {
    console.log(error);
  }
};

./views/auth/login.ejs

<%- include('../includes/head.ejs') %>
    <link rel="stylesheet" href="/css/forms.css">
    <link rel="stylesheet" href="/css/auth.css">
</head>

<body>
   <%- include('../includes/navigation.ejs') %>

    <main>
        <form class="login-form" action="/login" method="POST">
            <div class="form-control">
                <label for="email">E-Mail</label>
                <input type="email" name="email" id="email">
            </div>
            <div class="form-control">
                <label for="password">Password</label>
                <input type="password" name="password" id="password">
            </div>
            <input type="hidden" name="_csrf" value="<%= csrfToken %>">
            <button class="btn" type="submit">Login</button>
        </form>
    </main>
<%- include('../includes/end.ejs') %>

确实在 mongoDB 中创建了会话,但未定义用户或 isAuth(在下面的文档中显示为 isLoggedin)。

在缩小到 secure: true 问题之后(当我第一次询问时我不知道是什么导致了这种行为),我发现这个线程解释了 http 服务器没有得到 secure: true cookie ()

在 localhost 中,我使用 http,所以这当然行不通。当我把它放在生产环境中时它起作用了:)