我使用 MERN 堆栈创建了一个简单的发票应用程序。只要有一个用户登录,该应用程序就可以很好地处理已登录用户的数据,但如果另一个用户登录,则会显示第一个登录用户的发票。
我目前正在使用app.set()
和app.get()
在端点之间传递数据并发送到我的前端客户端。Auth0 处理身份验证层,但会express-session
解决这个问题吗?如果是这样,我将如何实施?或者有更好的解决方案吗?
以下是当前将发票发送到前端的代码:
var express = require('express');
var app = express();
var userInvoices = express.Router();
const axios = require('axios');
const InvoiceModel = require('../models/Invoice');
const UserModel = require('../models/User');
//Functions//
async function clientCall() {
const url = `${process.env.REACT_APP_SAVE_USER}`;
const axiosConfig = {
method: 'get',
url
};
await axios(axiosConfig).catch((e) => {console.log(e)});
};
async function fetchUsersFromDB() {
const usersFromDB = await UserModel.find().catch((e) => {console.log(e)});
return usersFromDB;
};
async function saveUser(User) {
const condition = {email: User.email};
const query = {
nickname: User.nickname,
name: User.name,
picture: User.picture,
email: User.email,
email_verified: User.email_verified,
sub: User.sub,
};
const options = { upsert: true };
const update = await UserModel.updateMany(condition, query, options).catch((e) => {console.log(e)});
// Log the amount of documents that where updated in the DB.
if(update.nModified > 0 ) {
console.log('Number of Users added or updated to DB:', update.nModified)
}
};
function findCommonUser(dbUser, User) {
if(dbUser.length <= 0) {
UserModel.create(User, () => {console.log('Users saved to database')});
console.log('An Error has occured with Database')
} else {
dbUser.forEach((DBElement) => {
if(User.email !== DBElement.email) {
saveUser(User);
}
})
}
console.log(' Users match')
};
function matchUserAndInvoice(dbInvoices, loggedInUser) {
let newArray = [];
dbInvoices.forEach(async (DBElement) => {
if(DBElement.customer_email === loggedInUser.email){
newArray.push(DBElement);
app.set('userInvoices', newArray);
}
})
}
// prevents user from having to refresh to get data.
clientCall();
userInvoices.post('/saveUser', async (req, res) => {
try {
const User = req.body;
const usersFromDB = await fetchUsersFromDB().catch((e) => {console.log(e)});
findCommonUser(usersFromDB, User);
app.set('Users', User)
} catch (error) {
console.log(error)
}
})
userInvoices.get('/fetchUserInvoices', async (req,res) => {
try {
const invoices = await InvoiceModel.find().catch((e) => {console.log(e)});
const user = await app.get('Users');
await matchUserAndInvoice(invoices,user);
const userInvoices = await app.get('userInvoices')
res.json(userInvoices);
} catch (error) {
console.log(error)
}
});
;
module.exports = userInvoices;
app.get()
对于您的服务器实例来说本质上是全局的,因此将数据放在单个用户的请求之间将(如您发现的那样)在不同用户之间混淆数据,因为所有用户都试图将数据存储在同一个地方。
解决此类问题的常用方法是使用express-session。此 cookie 会在最终用户第一次连接到您的服务器时与他们建立连接,然后创建一个自动与该 cookie 关联的服务器端对象。然后,在任何请求处理程序中,您可以读取或设置数据,req.session
并且该数据将唯一地属于该用户。
如果用户更换设备或清除他们的 cookie,那么与该用户的会话对象的关联将丢失(在他们下次连接时为他们创建一个新的会话对象)。但是,如果您有一个持久性数据存储,并且您使用某种登录名,允许您从用户的持久存储中填充会话,您甚至可以使同一用户的会话跨设备持久化(尽管这通常不是必需的) )。
在您在问题中描述的特定应用程序(跟踪发票)中,您的发票数据似乎应该在存储在数据库中时使用特定用户标记,然后任何未来显示发票的请求都应基于特定用户进行查询正在提出请求。这需要登录和登录 cookie,以便您可以唯一标识每个用户,从而仅向他们显示与他们相关的发票。
上述会话对象应仅用于临时会话状态,而不应用于诸如发票之类的持久存储。如果您的服务器实现是真正的 RESTFUL,您甚至可能不需要除了用户登录的用户 ID 之外存储在会话对象中的任何数据。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句