Express-session 未在浏览器中设置 cookie
Express-session is not setting cookies in browser
所以我使用 express-session
包来设置 cookie 和会话。它还连接到我的 MongoDB 商店以存储会话。当用户登录时,会话会很好地存储在数据库中,但是浏览器中没有 cookie。我的应用程序在 http://localhost:8080/
中是 运行,我的服务器在 http://localhost:5500/
中是 运行。
index.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));
router.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.');
}
});
});
浏览器:
所以在我给出答案之前我会说 JWT 不是处理会话的安全方式
如何处理Express-session
首先你需要以下软件包
npm i express-session connect-mongodb-session
或 yarn add 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,
},
})
);
现在会话中间件已准备就绪,但现在您必须设置 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,
})
);
现在我们的中间件都设置好了,让我们看看你的登录路径
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);
})
现在我们的服务器已准备就绪,但现在我们必须修复我们在客户端中发出请求的方式,以便此流程可以 100% 工作:
下面的代码:React 应用程序/任何 fron-tend 你在处理登录的地方使用
//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
});
};
有了这一切,您现在的服务器会话 cookie 为 httpOnly
所以我使用 express-session
包来设置 cookie 和会话。它还连接到我的 MongoDB 商店以存储会话。当用户登录时,会话会很好地存储在数据库中,但是浏览器中没有 cookie。我的应用程序在 http://localhost:8080/
中是 运行,我的服务器在 http://localhost:5500/
中是 运行。
index.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));
router.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.');
}
});
});
浏览器:
所以在我给出答案之前我会说 JWT 不是处理会话的安全方式
如何处理Express-session
首先你需要以下软件包
npm i express-session connect-mongodb-session
或 yarn add 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,
},
})
);
现在会话中间件已准备就绪,但现在您必须设置 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,
})
);
现在我们的中间件都设置好了,让我们看看你的登录路径
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);
})
现在我们的服务器已准备就绪,但现在我们必须修复我们在客户端中发出请求的方式,以便此流程可以 100% 工作:
下面的代码:React 应用程序/任何 fron-tend 你在处理登录的地方使用
//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
});
};
有了这一切,您现在的服务器会话 cookie 为 httpOnly