ASP .NET 自定义 RoleProvider 不尊重 cacheRolesInCookie=“true”

发布于 2024-09-10 08:27:01 字数 516 浏览 9 评论 0原文

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

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

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

I've implemented a custom role provider, and configured it in my web.config file like this:

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

I've overridden the GetRolesForUser function in my custom role provider, and I've stepped into it, and it works just fine - loads up 60 roles for the user I'm testing with. However, I've noticed that the GetRolesForUser gets called on every request that calls User.IsInRole. In other apps I've written, it only calls it once, then caches the result in the cookie. For some reason, the caching is not working for this app. Any ideas as to why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

吹泡泡o 2024-09-17 08:27:01

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

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

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

"The issue of when to cache (or not cache) in RolePrincipal went through a number of design iterations, and we finally settled on only caching for the method exposed by the IPrincipal interface (i.e. IsInRole). "

没企图 2024-09-17 08:27:01

我也遇到了同样的问题。就我而言,问题是我将 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);
        }

保存roleCookie

    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上并全局注册。请参阅此处

I was having the same problem. In my case the issue was that I was setting Context.User to GenericPrincipal and not RolePrincipal. So instead of:

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

this fixed for me:

            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
            }

The IsValidAuthCookie method checks for null and empty:

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

UPDATE: After upgrading to MVC5 .NET 4.5 roleManager stopped working (not saving roles in cookie) so had to save it myself:

        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);
        }

Save the roleCookie

    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);
        }
    }

Place this code on AuthenticationFilter and register it globally. See here.

烟织青萝梦 2024-09-17 08:27:01

对我来说也是如此。它不断调用 GetRolesForUser()

Same is true for me. It keeps calling GetRolesForUser()

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文