为什么我在使用 Passport 和会话时没有保持登录状态?护照的 "isAuthenticated()" 始终 returns 错误
Why I'm not kept logged in when using Passport and sessions? Passport's "isAuthenticated()" always returns false
我正在使用 Angular、Passport 和会话进行身份验证。我可以创建一个新用户,登录但是,
问题
在使用 Passport 的 isAuthenticated() 函数检查用户是否登录时总是 returns 错误。我按照各种在线资源的说明进行操作,但不确定是否:
问题
我可以在 Angular 应用程序中使用通行证和会话吗?或者我只是在我的代码中做错了什么?如果你们有任何 idea/hint 为什么它不起作用,我将非常感激。谢谢。
后端代码
const cors = require('cors');
const express = require("express");
const app = express();
const PORT = 3000;
const mongoose = require('mongoose');
const seedDB = require("./helpers/dbseed");
const session = require("express-session");
const passport = require("passport");
const LocalStrategy = require("passport-local");
// the model with Passport-Local Mongoose plugged in
const User = require("./models/user");
const Profile = require("./models/profile");
const Recipe = require('./models/recipe');
const Macro = require ("./models/macro");
const Micro = require ("./models/micro");
const Ingredient = require("./models/ingredient");
// const {isLoggedIn} = require("./middleware/auth");
mongoose.connect('mongodb://localhost:27017/foodAppCopy', {useNewUrlParser: true, useUnifiedTopology: true})
.then(() => {
console.log("Mongo Connection open");
})
.catch((error) => {
console.log("No, Mongo -> Connection Error " + error);
})
seedDB();
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.options('*', cors());
app.use(express.json());
const sessionConfig = {
secret: 'pass',
resave: false,
saveUninitialized: true,
cookie: {
httpOnly: true,
expires: Date.now() + 1000 * 60 * 60 * 24 * 7,
maxAge: 1000 * 60 * 60 * 24 * 7,
}
}
app.use(session(sessionConfig));
app.use(passport.initialize());
app.use(passport.session());
// passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
// Create New User
app.post('/register', async (req, res) => {
try {
const {name, email, password} = req.body;
const user = new User({name, email});
const registeredUser = await User.register(user, password);
// This is used to create a profile
res.send(registeredUser._id);
} catch(e) {
console.log(e.message);
}
});
// Login
app.post('/login', passport.authenticate('local', {successRedirect: '/recipes'}),
async(req, res) => {
});
// Create Profile
app.post('/profile', async(req, res) => {
const {userID, profileData} = req.body;
let user = await User.findOne({_id: userID});
if (user === null || user.length <= 0) {
return res.status(422).json("Could not create profile");
} else {
let newProfile = new Profile({
userID: user._id,
dob: profileData.dob,
gender:profileData.gender,
weightGoal:profileData.weightGoal,
weeklyLossFrequency:profileData.weeklyLossFrequency,
})
await newProfile.save();
}
});
// INDEX Recipes
app.get('/recipes', async (req, res) => {
if(!req.isAuthenticated()) {
console.log("error");
return res.status(422).json("You need to be logged in");
}
const recipes = await Recipe.find({});
res.send(recipes);
});
中间件文件
module.exports.isLoggedIn = (req, res, next) => {
if(req.isAuthenticated()) {
return next()
}
res.status(403).send("Please login");
}
[1]: https://i.stack.imgur.com/GsfG8.png
用户模型
const mongoose = require("mongoose");
const passportLocalMongoose = require("passport-local-mongoose");
const UserSchema = new mongoose.Schema({
email: {
type: String,
required: true,
},
})
UserSchema.plugin(passportLocalMongoose, {
usernameField: "email"
});
module.exports = mongoose.model("User",UserSchema);
控制台出错
我只是猜测出了什么问题,因为您在问题中没有准确说明应用程序的端口,但我认为它是 4200,因为我看到您已将这些行添加到原始项目中:
app.use(cors());
app.options('*', cors());
你可能是在遇到这种错误后添加的:
Access to fetch at 'http://localhost:3000/' from origin
'http://localhost:4200' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
如果我的假设是正确的,那么您遇到的问题是与端口 3000 上的后端 运行 和端口 4200 上的前端 运行 相关的另一个问题。
确实,您正在使用 session 并且您已将其配置为使用 cookie。但是,cookie 不会从另一个域发送(不同的端口被认为是不同的域),除非设置了一些特殊选项:
- HTTP 响应中的
access-control-allow-credentials: true
header
- HTTP请求中的
withCredentials
选项
SameSite=none
cookie 属性
这些选项往往会降低您网站的安全级别(其他 CORS 选项也是如此)。保持良好安全级别并避免这些错误的最简单解决方案是在同一端口上为前端和后端提供服务。
在本地环境中,这可以通过 Angular development proxy 完成,您可以这样配置:
{
"/backend": {
"target": "http://localhost:3000",
"secure": false,
"pathRewrite": {
"^/backend": ""
}
}
}
不要忘记 angular.json
文件中对该新文件的引用:
"proxyConfig": "src/proxy.conf.json"
之后,将所有后端调用从 http://localhost:3000/...
更改为 http://localhost:4200/backend/...
,您的登录应该可以正常工作(您也可以删除两条 CORS 行)。
我正在使用 Angular、Passport 和会话进行身份验证。我可以创建一个新用户,登录但是,
问题
在使用 Passport 的 isAuthenticated() 函数检查用户是否登录时总是 returns 错误。我按照各种在线资源的说明进行操作,但不确定是否:
问题
我可以在 Angular 应用程序中使用通行证和会话吗?或者我只是在我的代码中做错了什么?如果你们有任何 idea/hint 为什么它不起作用,我将非常感激。谢谢。
后端代码
const cors = require('cors');
const express = require("express");
const app = express();
const PORT = 3000;
const mongoose = require('mongoose');
const seedDB = require("./helpers/dbseed");
const session = require("express-session");
const passport = require("passport");
const LocalStrategy = require("passport-local");
// the model with Passport-Local Mongoose plugged in
const User = require("./models/user");
const Profile = require("./models/profile");
const Recipe = require('./models/recipe');
const Macro = require ("./models/macro");
const Micro = require ("./models/micro");
const Ingredient = require("./models/ingredient");
// const {isLoggedIn} = require("./middleware/auth");
mongoose.connect('mongodb://localhost:27017/foodAppCopy', {useNewUrlParser: true, useUnifiedTopology: true})
.then(() => {
console.log("Mongo Connection open");
})
.catch((error) => {
console.log("No, Mongo -> Connection Error " + error);
})
seedDB();
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.options('*', cors());
app.use(express.json());
const sessionConfig = {
secret: 'pass',
resave: false,
saveUninitialized: true,
cookie: {
httpOnly: true,
expires: Date.now() + 1000 * 60 * 60 * 24 * 7,
maxAge: 1000 * 60 * 60 * 24 * 7,
}
}
app.use(session(sessionConfig));
app.use(passport.initialize());
app.use(passport.session());
// passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
// Create New User
app.post('/register', async (req, res) => {
try {
const {name, email, password} = req.body;
const user = new User({name, email});
const registeredUser = await User.register(user, password);
// This is used to create a profile
res.send(registeredUser._id);
} catch(e) {
console.log(e.message);
}
});
// Login
app.post('/login', passport.authenticate('local', {successRedirect: '/recipes'}),
async(req, res) => {
});
// Create Profile
app.post('/profile', async(req, res) => {
const {userID, profileData} = req.body;
let user = await User.findOne({_id: userID});
if (user === null || user.length <= 0) {
return res.status(422).json("Could not create profile");
} else {
let newProfile = new Profile({
userID: user._id,
dob: profileData.dob,
gender:profileData.gender,
weightGoal:profileData.weightGoal,
weeklyLossFrequency:profileData.weeklyLossFrequency,
})
await newProfile.save();
}
});
// INDEX Recipes
app.get('/recipes', async (req, res) => {
if(!req.isAuthenticated()) {
console.log("error");
return res.status(422).json("You need to be logged in");
}
const recipes = await Recipe.find({});
res.send(recipes);
});
中间件文件
module.exports.isLoggedIn = (req, res, next) => {
if(req.isAuthenticated()) {
return next()
}
res.status(403).send("Please login");
}
[1]: https://i.stack.imgur.com/GsfG8.png
用户模型
const mongoose = require("mongoose");
const passportLocalMongoose = require("passport-local-mongoose");
const UserSchema = new mongoose.Schema({
email: {
type: String,
required: true,
},
})
UserSchema.plugin(passportLocalMongoose, {
usernameField: "email"
});
module.exports = mongoose.model("User",UserSchema);
控制台出错
我只是猜测出了什么问题,因为您在问题中没有准确说明应用程序的端口,但我认为它是 4200,因为我看到您已将这些行添加到原始项目中:
app.use(cors());
app.options('*', cors());
你可能是在遇到这种错误后添加的:
Access to fetch at 'http://localhost:3000/' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
如果我的假设是正确的,那么您遇到的问题是与端口 3000 上的后端 运行 和端口 4200 上的前端 运行 相关的另一个问题。
确实,您正在使用 session 并且您已将其配置为使用 cookie。但是,cookie 不会从另一个域发送(不同的端口被认为是不同的域),除非设置了一些特殊选项:
- HTTP 响应中的
access-control-allow-credentials: true
header - HTTP请求中的
withCredentials
选项 SameSite=none
cookie 属性
这些选项往往会降低您网站的安全级别(其他 CORS 选项也是如此)。保持良好安全级别并避免这些错误的最简单解决方案是在同一端口上为前端和后端提供服务。
在本地环境中,这可以通过 Angular development proxy 完成,您可以这样配置:
{
"/backend": {
"target": "http://localhost:3000",
"secure": false,
"pathRewrite": {
"^/backend": ""
}
}
}
不要忘记 angular.json
文件中对该新文件的引用:
"proxyConfig": "src/proxy.conf.json"
之后,将所有后端调用从 http://localhost:3000/...
更改为 http://localhost:4200/backend/...
,您的登录应该可以正常工作(您也可以删除两条 CORS 行)。