【问题标题】:ASP .NET Custom RoleProvider not respecting cacheRolesInCookie="true"ASP .NET 自定义 RoleProvider 不尊重 cacheRolesInCookie="true"
【发布时间】:2011-03-18 00:21:43
【问题描述】:

我已经实现了一个自定义角色提供程序,并在我的 web.config 文件中对其进行了如下配置:

<roleManager enabled="true" defaultProvider="TDRoleProvider" cacheRolesInCookie="true">
  <providers>
    <clear/>
    <add name="TDRoleProvider" type="TDRoleProvider"/>
  </providers>
</roleManager>

我已经在我的自定义角色提供程序中覆盖了 GetRolesForUser 函数,并且我已经介入了它,它工作得很好 - 为我正在测试的用户加载了 60 个角色。但是,我注意到在调用 User.IsInRole 的每个请求上都会调用 GetRolesForUser。在我编写的其他应用程序中,它只调用一次,然后将结果缓存在 cookie 中。由于某种原因,缓存不适用于此应用程序。关于为什么的任何想法?

【问题讨论】:

    标签: asp.net cookies forms-authentication roleprovider


    【解决方案1】:

    https://web.archive.org/web/20101123220352/http://connect.microsoft.com/VisualStudio/feedback/details/104688/rolemanager-cacherolesincookie-option-does-not-work

    “RolePrincipal 中何时缓存(或不缓存)的问题经历了多次设计迭代,最终我们决定只缓存 IPrincipal 接口暴露的方法(即 IsInRole)。”

    【讨论】:

    • 那么有什么更好的方法呢?我希望角色缓存在 cookie 中。
    • 我猜是反复试验并仔细选择要使用的方法。
    【解决方案2】:

    我遇到了同样的问题。就我而言,问题是我将 Context.User 设置为 GenericPrincipal 而不是 RolePrincipal。所以而不是:

    this.Context.User = new GenericPrincipal(customIdentity, roles);
    

    这对我来说是固定的:

                HttpCookie roleCookie = this.Context.Request.Cookies[Roles.CookieName];
                if (IsValidAuthCookie(roleCookie))
                {
                    this.Context.User = new RolePrincipal(customIdentity, roleCookie.Value);
                }
                else
                {
                    this.Context.User = new RolePrincipal(customIdentity);
                    var x = this.Context.User.IsInRole("Visitor"); // do this to cache the results in the cookie
                }
    

    IsValidAuthCookie 方法检查 null 和空:

        private static bool IsValidAuthCookie(HttpCookie authCookie)
        {
            return authCookie != null && !String.IsNullOrEmpty(authCookie.Value);
        }
    

    更新:升级到 MVC5 .NET 4.5 后,角色管理器停止工作(不在 cookie 中保存角色)所以必须自己保存:

            HttpCookie roleCookie = filterContext.HttpContext.Request.Cookies[Roles.CookieName];
            if (IsValidAuthCookie(roleCookie))
            {
                filterContext.Principal = new RolePrincipal(customIdentity, roleCookie.Value);
                RolePrincipal rp = (RolePrincipal)filterContext.Principal;
                if (!rp.IsRoleListCached) // check if roles loaded properly (if loads old cookie from another user for example, roles won't be loaded/cached).
                {
                    // roles not loaded. Delete and save new
                    Roles.DeleteCookie();
                    rp.IsInRole("Visitor"); // load Roles
                    SaveRoleCookie(rp, filterContext);
                }
    
            }
            else
            {
                filterContext.Principal = new RolePrincipal(customIdentity);
                filterContext.Principal.IsInRole("Visitor"); // do this to cache the results in the cookie.
                SaveRoleCookie(filterContext.Principal as RolePrincipal, filterContext);
            }
    

    保存角色Cookie

        private void SaveRoleCookie(RolePrincipal rp, AuthenticationContext filterContext)
        {
            string s = rp.ToEncryptedTicket();
            const int MAX_COOKIE_LENGTH = 4096;
            if (string.IsNullOrEmpty(s) || s.Length > MAX_COOKIE_LENGTH)
            {
                Roles.DeleteCookie();
            }
            else
            {
                HttpCookie cookie = new HttpCookie(Roles.CookieName, s);
                cookie.HttpOnly = true;
                cookie.Path = Roles.CookiePath;
                cookie.Domain = Roles.Domain;
                if (Roles.CreatePersistentCookie)
                    cookie.Expires = rp.ExpireDate;
                cookie.Secure = Roles.CookieRequireSSL;
                filterContext.HttpContext.Response.Cookies.Add(cookie);
            }
        }
    

    将此代码放在 AuthenticationFilter 上并全局注册。见here

    【讨论】:

    • 我已经在这个问题上搜索了几个小时,这解决了它!非常感谢你发布这个!你能回答一个问题,方法 IsValidAuthCookie 的参考是什么,或者实现该方法的代码是哪个类?
    • 感谢这个答案有很大帮助。这是当您实现 rown RoleProvider 时解决缓存不再在 MVC 5 中工作的唯一解决方案。我把它放在我自己的 Authorization 属性中。
    【解决方案3】:

    对我来说也是如此。它一直在调用 GetRolesForUser()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-02
      • 1970-01-01
      • 2020-02-01
      相关资源
      最近更新 更多