使用FormsAuthenticationTicket存储额外的用户会话对象 - cookie大小太大

时间:2013-01-22 05:44:47

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

我正在尝试设置.NET MVC 3项目来存储自定义用户会话对象(稍后可以在其他后续操作中从Custom Principal对象访问该对象) 我按照这里的步骤进行了操作: 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()从外部auth服务返回自定义用户会话对象),然后将其存储在FormsAuthenticationTicket

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

有没有其他安全的方法来存储这个用户会话对象,所以我不必继续查询数据库呢? 我听说将它存储在会话中是不安全的(因为会话劫持 - 它与成员资格分离。) - 那么我还有其他选择吗?

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

的问候, 马丁

1 个答案:

答案 0 :(得分:3)

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

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

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,因为我不知道你的提供者返回什么,所以如果它更具体,请确保使用该类。