PostAuthenticateRequest的开销是什么?

7
我正在使用global.asax文件中的Application_PostAuthenticateRequest方法(ASP.NET MVC)实现自定义工单系统。我想知道这种方法的开销是多少,因为它会在每个请求上反序列化一些信息。它生成了一个大约1.8 kb的cookie,这很多 - 但是这比频繁地访问数据库更好吗?
需要反序列化的信息如下:
- 用户ID(int) - 角色(string[]) - 电子邮件(string) - 相关ID(int[])//(很难描述这些是什么,但每个用户将拥有约3个)
实现自定义FormsAuthenticationTicket系统似乎比基于User.Identity.Name不断访问数据库更明智。但我担心这种持续的反序列化会非常阻碍。但它看起来像这样...
    protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
    {
        HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];

        if (authCookie != null)
        {
            string encTicket = authCookie.Value;

            if (!String.IsNullOrEmpty(encTicket))
            {
                // decrypt the ticket if possible.
                FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(encTicket);

                var userData = Deserializer.Deserialize(ticket);
                UserPrincipal principal = new UserPrincipal(userData);

                HttpContext.Current.User = principal;
            }
        }
    }

这里的类被序列化为UserData,在FormsAuthenticationTicket中使用。

[Serializable]
public class MembershipData
{
    public string Email
    {
        get;
        set;
    }

    public int Id
    {
        get;
        set;
    }

    public string[] Roles
    {
        get;
        set;
    }

    public int[] Ancillary
    {
        get;
        set;
    }
}

我有很多应用程序在外面执行这个确切的操作 - 将数据存储在表单身份验证票证的userData部分中。我不必反序列化,因为数据只是一个逗号分隔的列表,但我想象这对你来说不会成为瓶颈。你需要进行一些测试。 - ScottE
2个回答

8

我知道这个问题有点老了,已经有了一个被接受的答案,但我想分享一下我的想法以及我们目前在类似设置中所做的事情。

最初,我们正在进行与您相同的过程,并在cookie中包含了大量用户数据。这个过程确实减少了我们对数据库的访问次数,但最终我们遇到了一个错误:一些用户无法登录,而其他用户可以。结果发现,由于我们的序列化数据,当cookie超过一定大小时,它会被静默丢弃。

我们目前的处理方式是采用两层缓存系统。我们将用户的数据库ID作为User.Identity.Name存储在cookie中,然后在PostAuthenticateRequest上,我们尝试从本地ASP.net缓存中检索用户信息,如果没有则回退到分布式Redis缓存。本地缓存是in-proc并且存储15秒(因此重复请求不需要跨越网络到达Redis)。Redis缓存存储一天,并在更新时失效。如果这两者都不命中,则从SQL Server加载信息。

然后我们将该用户信息放入自定义的IPrincipal中,一切都很顺利。在我们使用的高流量网站中,这似乎运行得非常好。


2
我建议你测量性能,但我认为使用cookie的方法比向数据库进行往返传输更快。你还可以通过使用逗号分隔或一些特殊字符分隔的字符串来简化序列化并使其尽可能快。以下是我根据性能排名不同操作的方式:
  1. 进程内通信
  2. 进程间通信
  3. 网络间通信

即使cookie的大小为1.8kb,它仍然比经常往返要好吗?我在FireFox、Chrome和Safari中收到了有关cookie大小的警告...但我想不出其他存储所需信息的方法。我不能只依靠将其放入“会话”中,这与将其加载到cookie中一样糟糕,并且容易出现更多问题。我真的不能依赖缓存它,因为它需要绑定登录,并且使用依赖注入只意味着更多次往返数据库。 - Ciel
为了减小 cookie 的大小,您可以考虑使用自定义序列化来处理您的票据 - 我听说 Google Protocol Buffers 得到了很好的评价。 - Chris Moutray

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接