【问题标题】:Store extra user session object with FormsAuthenticationTicket - cookie size too large使用 FormsAuthenticationTicket 存储额外的用户会话对象 - cookie 太大
【发布时间】:2013-01-22 05:44:47
【问题描述】:

我正在尝试设置一个 .NET MVC 3 项目来存储自定义用户会话对象(以后可以在其他后续操作中从自定义主体对象访问该对象) 我已按照此处的步骤操作: ASP.NET MVC - Set custom IIdentity or IPrincipal (LukeP 说的 - 我也需要自定义会员等)

在我的登录操作中,我有这样的事情:


if (provider.ValidateUser(model.UserName, model.Password))
{
        // setup principal 
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        string userData = serializer.Serialize(provider.GetSession());

        FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
             1,
             model.UserName,
             DateTime.Now,
             DateTime.Now.AddMinutes(15),
             false,
            userData);

        string encTicket = FormsAuthentication.Encrypt(authTicket);
        HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
        Response.Cookies.Add(faCookie);

        if (!String.IsNullOrEmpty(returnUrl))
        {
            return Redirect(returnUrl);
        }
        else
        {
            return RedirectToAction("Index", "Home");
        }
}
else
{
    ModelState.AddModelError("", "The user name or password provided is incorrect.");
}

这基本上会获取用户对象(provider.GetSession() 从外部身份验证服务返回自定义用户会话对象),然后将其存储在 FormsAuthenticationTicket 中

问题是来自外部服务的用户会话对象超过 4Kb(大约 7Kb 已加密),并且由于大小,cookie 没有存储在浏览器中。

有没有其他安全的方法可以将此用户会话对象存储在某个地方,这样我就不必继续查询数据库了? 我听说将它存储在 Session 中是不安全的(因为会话劫持 - 并且它与成员资格分离。) - 那么我还有什么其他选择?

我无法减小自定义用户会话对象的大小 - 这不是一个选项,因为它的属性依赖于所有系统层调用。

问候, 马丁

【问题讨论】:

    标签: asp.net-mvc authentication asp.net-membership iprincipal


    【解决方案1】:

    我不明白您为什么不能将其存储在用户的会话对象中,因为您应该在他们每次执行特权操作时验证他们的表单身份验证。

    如果您真的不想将其存储在他们的会话中,您可以创建一个静态字典并将数据存储在那里:

    using System.Collections.Concurrent;
    
    // Class level declaration.
    static ConcurrentDictionary<string, object> UserData =
            new ConcurrentDictionary<string, object>();
    
    // Inside your magic method.
    if (provider.ValidateUser(...)) {
      object providerSession = provider.GetSession();
      string userId = Guid.NewGuid().ToString("n");
    
      UserData.TryAdd(userId, providerSession);
    
      FormsAuthenticatonTicket authTicket = new FormsAuthenticatonTicket(
        1,
        model.UserName,
        DateTime.Now,
        DateTime.Now.AddMinutes(15),
        false,
        userid);
    
      // ...
    }
    

    然后,您可以从那里根据表单身份验证票证中存储的userId 查找您的提供商会话数据。我将存储在字典中的对象设为标准 object,因为我不知道您的提供程序返回什么,所以如果它更具体,请务必改用该类。

    【讨论】:

    • 酷,我试试看 - TryAdd 应该是 AddOrUpdate 吗?因为如果用户会话已经存在,我想更新它
    • 我试过了,它似乎确实可以完成这项工作 - 尽管我更愿意将会话存储在 cookie 中(所以我不必去那里时从数据库中获取会话是内存刷新..该死的 4kb 限制
    猜你喜欢
    • 2018-05-31
    • 2017-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-15
    • 2011-08-04
    • 2014-11-30
    • 2023-04-09
    相关资源
    最近更新 更多