我已经纠结这个问题一天多了。我正在为食品配送网络和移动应用程序构建一个后端API。
我有设置护照与当地的策略对用户进行身份验证。
我目前有两种不同类型的用户1。用户2。每家餐厅都使用自己的猫鼬模型(如下面的代码所示)
我最初设置了订户注册登录,身份验证会话和cookie,一切都很好。
然后我继续为我的餐厅用户设置护照,以便餐厅能够登录他们的个人资料并对他们的餐厅及其列表等进行各种更改。
我发现我能够为Restaurant用户创建一个帐户,但是当尝试在passport中登录用户时会始终返回"未授权",当尝试使用isauthenticated()时,我得到了相同的响应。然而,每次我点击注册端点时,Passport都会很高兴地继续创建餐厅用户。一个餐厅用户会出现在我的数据库中,但当我试图登录他们并存储cookie时,我只会返回"未经授权"。
与订阅者所有工作正常,我已经检查了我的受限端点的身份验证,注册新的订阅者和登录订阅者与0问题。
通过我的测试,我已经意识到一些事情
-
Passport根本不使用本地策略,我可以把整个事情都黑掉,它仍然会注册订户,登录他们,并通过0问题的cookie检查身份验证。当将console.log放入策略时,我可以看到策略实际上根本没有被调用。这怎么可能发生,护照当然需要策略来完成它的工作?在这种情况下,它似乎不是,为什么?
-
最初,我试图为我的每个模型创建一个单独的策略,一个用于订户的策略和一个用于使用. createstrategy()的餐馆的策略,这返回了同样的问题,订户模型用户的所有功能都工作得很好,但是一旦我试图登录或为我的餐馆模型护照的用户存储cookie,就会返回"未经授权。然后,您将在server.js下的代码中看到,我试图创建一个本地策略,然后在so passport中构建if else检查订阅者和餐厅模型,通过这样做,我意识到passport根本没有使用该策略。
在这一点上,我已经准备好撕裂我的头发了,创建一个策略的意义是什么,护照在某种程度上完全绕过了它。如果我尝试用错误的凭据登录订阅服务器,护照会完成它的工作,不允许访问,那么它实际上是如何管理身份验证的呢?
下面是我的代码,任何人可以帮助这将超过我的一天!
Server.js:
require("dotenv").config();
const express = require("express");
const mongoose = require("mongoose");
const app = express();
const cors = require("cors")
const bodyParser = require("body-parser");
const passport = require("passport");
const session = require("express-session");
const LocalStrategy = require('passport-local').Strategy;
mongoose.connect(process.env.DATABASE_URL)
const db = mongoose.connection
db.on("error", () => console.error(error))
db.once("open", () => console.log("connected to database"))
// app.use(express.json())
// Use JSON parser for all non-webhook routes
app.use((req, res, next) => {
// console.log(req.originalUrl)
if (req.originalUrl === "/subscribers/webhook") {
next();
} else {
bodyParser.json()(req, res, next);
}
});
app.use(cors())
//INITIAL STRATEGY i TRIED
// passport.use(new LocalStrategy(
// function (username, password, done) {
// Subscriber.findOne({
// username: username
// }, function (err, user) {
// if (err) {
// return done(err);
// }
// if (!user) {
// return done(null, false);
// }
// if (!user.verifyPassword(password)) {
// return done(null, false);
// }
// return done(null, user);
// });
// }
// ));
app.use(session({
secret: "foodsecrets",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
// sTRATEGY i WROTE TO TRY SEPERATE THE MODELS BEFORE I REALIZED THE STRATEGY WAS NOT BEING CALLED AT ALL
passport.use(new LocalStrategy(function (username, password, done) {
Subscriber.findOne({
username: username,
password: password
}, function (err, user) {
console.log("called")
// first method succeeded?
if (!err && user && passwordMatches(password)) {
return done(null, user);
}
// no, try second method:
Restaurant.findOne({
name: username,
password: password
}, function (err, user) {
// second method succeeded?
if (!err && user && passwordMatches(password)) {
return done(null, user);
}
// fail!
done(new Error('invalid user or password'));
});
});
}));
const subscribersRouter = require("./routes/subscribers")
const restaurantsRouter = require("./routes/restaurants")
const ordersRouter = require("./routes/orders")
const seederRouter = require("./routes/seeder");
app.use("/subscribers", subscribersRouter)
app.use("/restaurants", restaurantsRouter)
app.use("/orders", ordersRouter)
app.use("/seeder", seederRouter)
app.listen(3000, () => {
console.log("Server has started on port 3000")
});
用户模型:
const mongoose = require("mongoose")
const passportLocalMongoose = require("passport-local-mongoose");
const cartSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
description: {
type: String,
required: true
},
categories: {
type: Array,
required: true
},
rating: {
type: String
},
restaurantname: {
type: String
}
});
const favouritesSchema = new mongoose.Schema({
favouritemeals: {
type: Array
},
favouriteresturants: {
type: Array
}
});
const pendingItemsSchema = new mongoose.Schema({
name: String,
price: Number,
description: String
});
const pendingOrderSchema = new mongoose.Schema({
userID: {
type: String,
required: true
},
total: {
type: Number,
required: true
},
items: [pendingItemsSchema],
removeItem: {
type: String
},
orderData: {
type: Date,
required: true,
default: Date.now
},
status: {
type: String
}
});
const subscriberSchema = new mongoose.Schema({
googleID: {
type: String
},
facebookID: {
type: String
},
username: {
type: String,
required: true
},
email: {
type: String,
},
subscribeData: {
type: Date,
required: true,
default: Date.now
},
orderHistory: {
type: Array,
},
favourites: {
favouritesSchema
},
cart: [cartSchema],
login: {
type: String,
},
pendingOrder: [pendingOrderSchema],
stripeCustId: {
type: String,
required: true
},
role:{
type: String,
// required: true
}
});
subscriberSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("subscriber", subscriberSchema);
subscriber .js
const express = require("express");
const router = express.Router();
const Subscriber = require("../models/subscriber");
const Restaurant = require("../models/restaurant");
const passport = require("passport");
const Order = require("../models/order");
const bodyParser = require("body-parser");
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const facebookStrategy = require('passport-facebook').Strategy;
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY)
const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET
// passport.use(Subscriber.createStrategy());
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
Subscriber.findById(id, function (err, user) {
done(err, user);
});
});
subscriptions .js登录端点:
// LOGIN USING PASSPORT JS
router.post("/login", (req, res) => {
const subscriber = new Subscriber({
username: req.body.username,
password: req.body.password,
email: req.body.email
});
req.login(subscriber, async function (err) {
if (err) {
console.log(err)
} else {
try {
passport.authenticate("LocalStrategy")(req, res, function () {
console.log("Authenticated")
res.status(201).json("authenticated")
})
} catch (err) {
res.status(400).json({
message: err.message
})
}
}
})
})
subscriber .js注册端点:
// REGISTER USING PASSPORT JS
router.post("/register", async (req, res) => {
const customer = await stripe.customers.create({
name: req.body.username,
email: req.body.email
});
console.log("customer", customer)
Subscriber.register({
username: req.body.username,
email: req.body.email,
stripeCustId: customer.id
}, req.body.password, async (err, subscriber) => {
if (err) {
console.log(err)
} else {
try {
await passport.authenticate("local")(req, res, function () {
console.log("is authenticated")
res.status(201).json(newSubscriber)
})
const newSubscriber = await subscriber.save()
} catch (err) {
res.status(400).json({
message: err.message
})
}
}
});
})
餐厅模型:
const mongoose = require("mongoose")
const passportLocalMongoose = require("passport-local-mongoose");
const menueItemSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
description: {
type: String,
required: true
},
categories: {
type: Array,
required: true
},
rating: {
type: Number
},
restaurantname: {
type: String
}
})
const activeOrderSchema = new mongoose.Schema({
userID: {
type: String,
required: true
},
total: {
type: Number,
required: true
},
items: [menueItemSchema
],
orderData: {
type: Date,
required: true,
default: Date.now
},
status: {
type: String
}
})
const restaurantSchema = new mongoose.Schema({
username: {
type: String,
required: true
},
email: {
type: String,
},
src: {
type: String,
required: true
},
title: {
type: String,
required: true
},
description: {
type: String,
required: true
},
menue: [menueItemSchema],
rating: {
type: String
},
categories: {
type: String
},
subscribeData: {
type: Date,
required: true,
default: Date.now
},
activeOrders: [activeOrderSchema]
})
restaurantSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("restaurant", restaurantSchema)
Restaurants.js:
const express = require("express")
const router = express.Router()
const Restaurant = require("../models/restaurant")
const passport = require("passport");
const randomRest = require("randomrestgenerator")
// passport.use(Restaurant.createStrategy());
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
Restaurant.findById(id, function (err, user) {
done(err, user);
});
});
Restaurants.js登录端点:
router.post("/login", (req, res) => {
const restaurant = new Restaurant({
username: req.body.username,
password: req.body.password,
email: req.body.email
});
req.login(restaurant, async function (err) {
if (err) {
console.log(err)
} else {
try {
passport.authenticate("local")(req, res, function () {
console.log("Authenticated")
res.status(201).json("authenticated")
})
} catch (err) {
res.status(400).json({
message: err.message
})
}
}
})
})
Restaurants.js注册端点
// PASSPORT JS RESTAURANT REGISTRATION
router.post("/register", async (req, res) => {
const randomRestaurant = randomRest()
Restaurant.register({
username: req.body.username,
email: req.body.email,
src: randomRestaurant.img,
title: randomRestaurant.title,
description: randomRestaurant.description,
menue: randomRestaurant.menue,
rating: randomRestaurant.rating,
categories: randomRestaurant.categories
}, req.body.password, async (err, restaurant) => {
if (err) {
console.log(err)
} else {
try {
console.log("try called")
const newRestaurant = await restaurant.save()
await passport.authenticate("rest")(req, res, function () {
console.log("is authenticated")
res.status(201).json(newRestaurant)
})
} catch (err) {
console.log("here!")
res.status(400).json({
message: err.message
})
}
}
});
几天前我设法修复了这个问题,原来我把JSON响应留在了护照之外。餐厅登录端点中的身份验证回调函数。
我将序列化和反序列化以及我的会话和护照初始化以及护照会话。use移到了server.js中
还必须使用if else ' s设置我的序列化和反序列化用户函数,以便它们服务于两个模型。
最后,我在会话中添加了一个秘密数组,而不仅仅是一个字符串。
一切正常。
passport.serializeUser(function (user, done) {
if (user instanceof Subscriber) {
done(null, {
id: user.id,
type: "Subscriber"
});
console.log("sub user")
} else {
console.log("rest user")
done(null, {
id: user.id,
type: "Restaurant"
})
}
});
passport.deserializeUser(function (id, done) {
console.log("de-serialize called")
console.log("id type", id.type)
console.log("ID", id)
if (id.type === "Subscriber") {
Subscriber.findById(id.id, function (err, user) {
done(err, user);
})
} else {
Restaurant.findById(id.id, function (err, user) {
done(err, user);
})
}
});