2016-08-28 41 views
2

在我的应用程序中,我已经实现了更改用户权限,级别等的功能。如果更新我自己的权限,我可以立即看到更改,因为我可以通过req.login()更新req.user对象。问题是,当我更新其他用户权限时,它在数据库中的更新很好,但用户将不得不重新登录才能看到他们的权限更改,因为req.user仍然认为他们没有权限。这很好,如果他们没有登录当然,但如果他们是,我希望这些更改立即反映给他们,如果可能的话。PassportJS - 是否有可能为其他用户更改req.user?

所以我想知道是否有办法更新另一个用户req.user对象,以便他们可以立即看到他们的权限变化,而无需注销并重新登录?

或者可能的方式来退出并登录该用户之前返回?

回答

1

由于权限位于您自己的数据库中,因此确定您可以,但如何执行取决于您的应用程序。

鉴于您正在使用会话,通过使用您提供的函数passport.deserializeUser,存储在req.user中的对象将分别加载到每个HTTP请求中。通常,您可以将用户标识存储到passport.serializeUser中的会话中,然后从数据库中检索具有deserializeUser中的标识的用户。因此,无论何时在后端处理请求,您通常都会获得req.user中的最新信息,包括权限。当然,你的前端也需要以某种方式获得新的权限并进行自我调整(例如,如果你添加管理员权限给用户,你可能会希望他们看到UI中的管理员选项)。

您当然可以将整个用户对象传递给会话存储,并且每个请求跳过一个数据库调用,即。使用这些:

passport.serializeUser(function(user, cb) { cb(null, user); }); 
passport.deserializeUser(function(user, cb) { cb(null, user); }); 

用于会话处理。如果您这样做,则数据库更改不会反映在req.user对象上。如果用户更新了自己的信息,则可以拨打req.logIn(...),但不能拨打其他用户。你可以解决这个问题 - 例如。通过websocket通知有问题的用户,并让他们的浏览器调用一个路由,用最新的用户对象调用req.logIn,或者直接进入会话存储并操作数据。

或者,由于强制注销是一种选项,您可以按照enRaisers的回答并从会话存储中找到用户会话,并将其全部删除,从而有效地将用户从后端注销。您可以通过API访问会话,或者使用数据库(例如。connect-mongoconnect-redis)用于会话存储,您还可以打开到同一数据库的另一个连接并使用正常的搜索和销毁方法。您仍然需要以某种方式再次处理前端的注销。

+0

感谢您的回应。所以我改变了我的反序列化函数来从数据库中获取用户,现在'req.user'会在用户刷新页面后更新。我考虑的越多,我认为问题的根源在于我基于'req.user'验证了权限,以避免每次有人执行基于权限的操作时都会运行db查询(这很容易发生)。作为比我更有经验的人,你认为使用db查找来验证用户权限是正确的,而不是试图始终更新'req.user'?这不完全是一个巨大的应用程序。 –

+0

一般来说,我会说跳过一个查询,其中一个项目被它的ID所取代是微型优化,并且在'deserializeUser'中击中数据库从未成为我项目中的问题。我查询的唯一ID是几乎每个数据库中可能最快的查询方法,并且通常如果你一直询问同一行,数据库会做一些事情来加快速度。仅供参考,我通过我的14M行Postgres数据库查询了一行ID,第一个查询是65ms。具有相同ID的第二个查询是0.063ms。 – vesse

+0

是的。感谢您的建议!我最终通过改变我的护照反序列化方法来解决这个问题:'passport.serializeUser(function(user,done){ done(null,user.id); }); passport.deserializeUser(功能(ID,完成){ User.findById(ID,功能(ERR,用户){ DONE(ERR,用户); }); });'这保持'req.user '最新。在前端(我的情况是Angular 1),我还通过调用一个返回'req.user'的路由来更新每个路由变化的用户,以保持视图更新。希望这可以帮助别人:) –

0

您可以尝试删除会话或重新生成sessionID。但是这会强制该用户重新登录。

如果您的会话存储在mongodb中。那么你可以按名称检查收集app_sessions它有一个字段的名字userId

在Express会话中有一个名为store的模块。它提供了很多API来通过sessionID查找会话。但不幸的是,没有API通过userID查找会话。

所以,如果你想使用session store API那么你可以调用store.all,它会给所有的会话。但这是非常残酷的方法。因为我不知道它可能持有多少数据。

+0

我确实使用了Mongodb,但没有包含app_sessions的集合。 另外从我可以告诉,它看起来像注销用户会删除会议这是我的罚款,但我怎么能做到另一个用户? –

+0

你很多人使用connect-mongo模块来存储DB – enRaiser

相关问题