【发布时间】:2014-12-26 19:34:40
【问题描述】:
在 ASP.NET MVC 中,我将用户对象及其权限保存在 Session 中,这样我就不必每次都访问数据库。所以我使用 Session 作为缓存。例如:
当用户登录时:
User user = dbContext.Users.Include(u => u.Privileges).SingleOrDefault(u => u.UserId == userId)
Session["CurrentUser"] = user;
当用户发出未来的请求时:
public ActionResult CreateSomething()
{
User user = Session["CurrentUser"];
if (user == null)
{
// Error: not logged in
}
if (!user.Privileges.Any(p => p.PrivilegeId == PrivilegesEnum.CreateSomething))
{
// Error: doesn't have privilege
}
...
}
如您所见,“.Any(...)”将在内存中工作,这比进入数据库要快。
问题是其他用户可以撤销或添加已登录用户的权限,而这些已登录用户只有在下次登录时才能感知到这些更改。
public ActionResult RevokePrivilege(long targetUserId, long privilegeId)
{
...
targetUser.Privileges.Remove(privilege)
dbContext.SaveChanges();
// ... (*)
}
问题是:我可以访问 (*) 中的其他会话,以便我也可以在内存中进行这些更改吗?
类似的东西(我在这里发明)
foreach (var kvp in SessionDictionary.Where(kvp => kvp.Value.UserId == user.UserId).ToList())
{
SessionDictionary[kvp.Key]["CurrentUser"].Privileges.Remove(privilege);
}
【问题讨论】:
-
你需要使用
Cache来存储用户实体,你可以使用Session来存储当前用户的密钥。这样您就可以在权限更改时更新用户 -
@VsevolodGoloviznin 但如果 IIS 决定终止进程,
Cache将被清除?我喜欢Session的一点是,如果进程终止,它不会被清除。 -
@sport 用户会话 cookie 将保持不变,但服务器上的 InProc 会话状态将被清除,除非您使用的是 StateServer 或 Sql。如果您使用的是 Sql,您总是可以直接在数据库中进行挖掘。对于 InProc,似乎有 2 hacks to get at SessionState - 反射,并绑定您自己的 SessionStart 订阅者。可能将用户的角色保留在 Session 中,但将实际的 RolePriviledges 保留在
Application级缓存中? -
@StuartLC 如果我将会话超时设置为 10 分钟:
<sessionState timeout="10" mode="InProc" customProvider="DefaultSessionProvider">,并且当会话存在 2 分钟时进程被 IIS 杀死,然后进程由 IIS 再次启动(1 分钟后),用户还会在Session["currentUser"]中吗?还是不会?我知道 cookie 会的。 -
@sports 对于这种情况,您可以使用外部缓存系统(如 redis),但是获取用户实体对您来说如此昂贵?此外,afaik 不建议在会话对象中存储大对象
标签: asp.net asp.net-mvc session