7

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

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

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

4

3 回答 3

3

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

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

于 2010-09-10T20:04:36.817 回答
3

我遇到了同样的问题。就我而言,问题是我将 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 roleManager 后停止工作(不在 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 上并全局注册。见这里

于 2013-05-25T14:02:19.890 回答
1

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

于 2010-08-21T22:13:10.067 回答