在哪里使用Forms身份验证在ASP.NET MVC上存储已记录的用户信息?

时间:2009-11-30 18:08:04

标签: asp.net-mvc session forms-authentication

我在我的应用程序上使用ASP.NET MVC和Forms Authentication。基本上我使用FormsAuthentication.SetAuthCookie登录并FormsAuthentication.SignOut注销。

在HttpContext.Current.User.Identity中我存储了用户名,但我需要有关已登录用户的更多信息。我不想将我的整个User obj存储在Session中,因为它可能很大并且信息量比我需要的多得多。

你认为创建一个名为LoggedUserInfo的类只有我需要的属性,然后将其添加到Session variable是一个好主意吗?这是一个好方法吗?

或者你有更好的想法吗?

4 个答案:

答案 0 :(得分:8)

我使用这个解决方案:

ASP.NET 2.0 Forms authentication - Keeping it customized yet simple

总结:我创建了自己的IPrincipal实现。它存储在HttpContext.Current.Cache中。如果它以某种方式丢失,我有来自客户端授权cookie的用户名并且可以重建它。这个解决方案不依赖于Session,因为Session很容易丢失。

修改

如果您想在控制器中使用您的主体并使其可测试,您可以这样做:

    private MyPrincipal _myPrincipal;
    MyPrincipal MyPrincipal
    {
        get
        {
            if (_myPrincipal == null)
                return (MyPrincipal)User;
            return _myPrincipal;
        }
        set
        {
            _myPrincipal = value;
        }
    }

在测试中,您将设置准备进行测试的对象。否则它将从HttpContext中获取。现在我开始思考,为什么我要用Ninject来做呢?

答案 1 :(得分:4)

我实际上喜欢使用我在登录操作方法中设置的CustomPrincipal和CustomIdentity,如

        if (!String.IsNullOrEmpty(username) && !String.IsNullOrEmpty(password) && _authService.IsValidLogin(username, password))
        {
            User objUser = _userService.GetUserByName(username);
            if (objUser != null)
            {
                //** Construct the userdata string
                string userData = objUser.RoleName + "|" + objUser.DistrictID + "|" + objUser.DistrictName + "|" + objUser.ID + "|" + objUser.DisplayName;
                HttpCookie authCookie = FormsAuthentication.GetAuthCookie(username, rememberMe.GetValueOrDefault());
                FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(authCookie.Value);
                FormsAuthenticationTicket newTicket = new FormsAuthenticationTicket(ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration, ticket.IsPersistent, userData);
                authCookie.Value = FormsAuthentication.Encrypt(newTicket);
                Response.Cookies.Add(authCookie);
                return RedirectToAction("Index", "Absence");
            }
            else
            {
                return RedirectToAction("LogOn", "Account");
            }
        }
        else
        {
            return RedirectToAction("LogOn", "Account");
        }

然后在自定义主体中,您可以使用方法访问传递给构造函数的特定信息,如

((CustomIdentity)((CustomPrincipal)HttpContext.Current.User).Identity).DisplayName;

在CustomIdentity类中声明DisplayName属性。

答案 2 :(得分:3)

将其存储在会话中。

例如

// Make this as light as possible and store only what you need
public class UserCedentials
{
    public string Username { get; set; }
    public string SomeOtherInfo { get; set; }
    // etc...
}

然后当他们登录时,只需执行以下操作即可保存用户信息:

// Should make typesafe accessors for your session objects but you will
// get the point from this example
Session["UserCredentials"] = new UserCredentials()
    { Username = "SomeUserName", SomeOtherInfo = "SomeMoreData" };

然后,只要你需要它就可以获取它:

UserCredentials user = (UserCredentials)(Session["UserCredentials"]);

关于在MVC中进行自定义授权,我写了几个问题/答案: How to implement authorization checks in ASP.NET MVC based on Session data?

How does the Authorize tag work? - Asp.net Mvc

答案 3 :(得分:2)

那么你必须把这些存放在某个地方。可能有两个主要的地方:

服务器

您可以将它们放入Session。我建议你创建一个单独的类,它只包含你实际需要避免浪费太多内存的数据。或者你也可以存储到Cache中,当有大量并发用户时,最终可能会有很多数据库调用。

客户

在这种情况下,如果您可以使用单独的类限制数据量,并使用任何方式将其序列化并将其发送到客户端。在cookie或URI中(如果长度允许和cookie被禁用)......

这些想法的结果:
如果你以这种方式获得大量内存资源,那么这里最重要的是创建一个单独的类。所以这是你应该做的第一件事。