Express-session 未在浏览器中设置 cookie

pas*_*ner 9 mongodb session-cookies node.js express express-session

所以我使用express-session包来设置cookie和会话。它还连接到我的 MongoDB 存储来存储会话。当用户登录时,会话会很好地存储在数据库中,但浏览器中没有 cookie。我的应用程序正在运行http://localhost:8080/,我的服务器正在运行http://localhost:5500/

索引.js:

const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const expressSession = require('express-session');
const mStore = require('./model/database.js').Mstore;
const routes = require('./control/router.js');
const mongooseConnect = require('./model/database.js').mongooseConnect;


app.use(
   expressSession({ 
      secret: 'my secret', 
      resave: false, 
      saveUninitialized: false,
      store: mStore
   }),
   bodyParser.urlencoded({ extended: true }),
   bodyParser.json(),
   routes
);


mongooseConnect(() => app.listen(process.env.PORT || 5500));
Run Code Online (Sandbox Code Playgroud)

路由器.js:

const express = require('express');
const router = express.Router();
const notesModel = require('../model/database.js').notesModel;
const userModel = require('../model/database.js').userModel;
const cors = require('cors');

router.options('/login', cors());

router.post('/login', cors(), (req, res) => {
   userModel.findOne({ admin_username: req.body.username, admin_password: req.body.password }, (err, data) => {
      if (err) return console.log(err);
      
      if (data) {
         req.session.isLoggedIn = true; // Saves in database just fine.
         res.status(200).json('Login Success'); // This line works just fine as well.
      } else {
         console.log(req.session.isLoggedIn);
         res.status(401).json('Login Failed: Incorrect ID or Password.');
      }
   });
});
Run Code Online (Sandbox Code Playgroud)

浏览器: 在此输入图像描述

Nts*_*ane 20

因此,在给出答案之前,我想说 JWT 不是处理会话的安全方法

如何处理 Express-Session

首先你需要以下包

npm i express-session connect-mongodb-session或纱线添加express-session connect-mongodb-session

现在我们有了设置 mongoStore 和 express-session 中间件所需的包:

//Code in server.js/index.js (Depending on your server entry point)
import expressSession from "express-session";
import MongoDBStore from "connect-mongodb-session";
import cors from "cors";
const mongoStore = MongoDBStore(expressSession);

const store = new mongoStore({
  collection: "userSessions",
  uri: process.env.mongoURI,
  expires: 1000,
});
app.use(
  expressSession({
    name: "SESS_NAME",
    secret: "SESS_SECRET",
    store: store,
    saveUninitialized: false,
    resave: false,
    cookie: {
      sameSite: false,
      secure: process.env.NODE_ENV === "production",
      maxAge: 1000,
      httpOnly: true,
    },
  })
);
Run Code Online (Sandbox Code Playgroud)

现在会话中间件已准备就绪,但现在您必须设置 cors 来接受您的 ReactApp,以便传递 cookie 并由服务器将其设置在其中

//Still you index.js/server.js (Server entry point)

app.use(
  cors({
    origin: "http://localhost:3000",
    methods: ["POST", "PUT", "GET", "OPTIONS", "HEAD"],
    credentials: true,
  })
);
Run Code Online (Sandbox Code Playgroud)

现在我们的中间件已全部设置完毕,让我们看看您的登录路线

router.post('/api/login', (req, res)=>{
    //Do all your logic and now below is how you would send down the cooki

    //Note that "user" is the retrieved user when you were validating in logic
    // So now you want to add user info to cookie so to validate in future
    const sessionUser = {
       id: user._id,
       username: user.username,
       email: user.email,
    };
    //Saving the info req session and this will automatically save in your     mongoDB as configured up in sever.js(Server entry point)
    request.session.user = sessionUser;

    //Now we send down the session cookie to client
    response.send(request.session.sessionID);

})
Run Code Online (Sandbox Code Playgroud)

现在我们的服务器已准备就绪,但现在我们必须修复在客户端中发出请求的方式,以便此流程可以 100% 工作:

下面的代码:React App/您在处理登录时使用的任何前端

//So you will have all your form logic and validation and below
//You will have a function that will send request to server 

const login = () => {
    const data = new FormData();
    data.append("username", username);
    data.append("password", password);

    axios.post("http://localhost:5000/api/user-login", data, {
      withCredentials: true, // Now this is was the missing piece in the client side 
    });
};
Run Code Online (Sandbox Code Playgroud)

现在,有了这一切,您现在就拥有了 httpOnly 的服务器会话 cookie

  • “response”(如“response.send(request.session.sessionID)”)从哪里来? (2认同)

小智 5

我遇到了这个问题,在尝试了这里已经强调的大部分内容后,没有一个仍然对我有用。然而,在进一步挖掘之后,我意识到当在localhost上运行时。cookie 对象的secure属性应始终设置为false我的 Express 应用程序中以下代码片段为我解决了这个问题。

app.use(
    session({
        store: new RedisStore({ client: redisClient}),
        name: 'qid',
        secret: 'superdupersecret',
        resave: false,
        saveUninitialized: false,
        cookie: {
            httpOnly: true,
            secure: false,
            maxAge: 1000 * 60 * 60 * 24 * 365
        }
    })
);
Run Code Online (Sandbox Code Playgroud)
需要注意的主要变化是secure:false