【问题标题】:Where to store .net user roles between page requests在页面请求之间存储 .net 用户角色的位置
【发布时间】:2012-12-04 16:36:16
【问题描述】:

我有一个网站,它实现了自己的基于表单的登录,并创建了一个像这样的身份验证 cookie:

    FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, userID, DateTime.UtcNow, expiration, isPersistent, userFunctions);
    HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(ticket));
    cookie.Expires = expiration;
    HttpContext.Current.Response.Cookies.Add(cookie);

变量“userFunctions”包含用户所属角色的逗号分隔列表。

在我的 Global.asax 文件中,我通过以下方式检索这些用户函数:

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
    if (HttpContext.Current.User != null)
    {
        if (HttpContext.Current.User.Identity.IsAuthenticated)
        {
            if (HttpContext.Current.User.Identity is FormsIdentity)
            {
                FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;

                string[] roles = id.Ticket.UserData.Split(',');
                HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(id, roles);
            }
        }
    }
}

这一切都很好。或者直到我不得不为一群全新的用户更改它。新用户的问题是“userFunctions”变量可能会变得很长,并且太长而无法存储在 cookie 中(大小限制为 4k 之类的)。

我会更改我的代码以将“userFunctions”存储在会话中,但 Application_AuthenticateRequest 无法使用会话。我可以将数据存储在应用程序缓存中(可能是键/值对),但我犹豫是否这样做,因为应用程序缓存似乎不是放置这些数据的“正确”位置。

我可能最终会将其放入应用程序缓存中,但在此之前我想我会问一下,看看是否有人有更好的选择?

【问题讨论】:

  • 为什么要将用户所属的角色列表添加到 cookie 中?
  • 如果您将此列表发送给客户端(作为 cookie),最终用户是否可以更改它?我没想到你会想要这个。如果您要在两次通话之间维护此列表,我建议您将其保留在服务器上。
  • 我同意。这绝对听起来像服务器端功能。也许您可以拆分身份验证/授权功能来完成此操作...
  • @Jeroen - 我将角色存储在 cookie 中,因为那是我继承的代码。
  • @PeteH / Cal279:我同意。它应该留在服务器上,我想重写这部分代码,以便它确实留在服务器上,但由于会话状态不可用,我找不到任何合乎逻辑且适合存储角色的地方,以便我可以添加它们回到 HttpContext.Current.User

标签: asp.net .net-3.5 forms-authentication asp.net-caching


【解决方案1】:

鉴于我不能使用 Session 来存储用户角色(因为在授权发生之前我无法检索它们),并且我不希望每次页面请求都访问数据库的费用,我最终存储应用缓存中的角色:

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
    if (HttpContext.Current.User != null)
    {
        if (HttpContext.Current.User.Identity.IsAuthenticated)
        {
            if (HttpContext.Current.User.Identity is FormsIdentity)
            {
                FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;

                string[] roles;
                string cachedRoles = (string)HttpContext.Current.Cache.Get("UserFunctions" + id.Name.ToLower());
                if (cachedRoles == null)
                {
                    // Reload UserFunctions and add back in to Cache.

                    cachedRoles = [...code to get UserFunctions from database...];

                    HttpContext.Current.Cache.Insert("UserFunctions" + id.Name.ToLower(), cachedRoles, null, System.Web.Caching.Cache.NoAbsoluteExpiration, new TimeSpan(0, 20, 0), System.Web.Caching.CacheItemPriority.NotRemovable, null);

                }

                roles = cachedRoles.Split(',');

                HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(id, roles);
            }
        }
    }
}

它似乎工作正常(尽管到目前为止测试有限)。

【讨论】:

  • 以这种方式使用缓存是一个非常合理的解决方案。但是,我会通过实现自定义 RoleProvider 来做到这一点,而不是将代码放在 global.asax 中。有关如何执行此操作的详细信息,请参阅以下文章:msdn.microsoft.com/en-us/library/8fw7xh74(v=vs.100).aspx
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-15
  • 1970-01-01
  • 1970-01-01
  • 2015-09-10
  • 1970-01-01
相关资源
最近更新 更多