代码之家  ›  专栏  ›  技术社区  ›  Jeff Ancel

像Stack Overflow这样的站点如何在ASP.NET MVC中传递用户信息?

  •  4
  • Jeff Ancel  · 技术社区  · 16 年前

    基本上,我使用OpenID登录我的网站,这与我假设的非常相似。当我取回信息时,我把它扔到数据库中并创建我的“注册用户”。我设置了我的Authcookie:

    FormsAuthentication.SetAuthCookie(user.Profile.MyProfile.DisplayName, false);
    

    然后我可以用这个作为用户名。但是,我希望传递整个对象,而不仅仅是显示名称的字符串。所以我的问题是:

    怎么做到的?

    它们是否扩展/覆盖 SetAuthCookie(string, bool) 接受用户对象的方法,即 SetAuthCookie(User(object), bool) .

    保持一个用户对象以便我的用户控件可以在我的Web应用程序的每个页面上使用它,最好的方法是什么?

    事先谢谢!

    3 回复  |  直到 16 年前
        1
  •  3
  •   DreamSonic    16 年前

    你可以通过 implementing 你习俗 Membership Provider 或扩展现有的。提供程序基于密钥(或仅按用户名)存储用户信息,并提供对 MembershipUser 类,您可以随意扩展。所以当你打电话的时候 FormsAuthentication.SetAuthCookie(...) ,您基本上设置了用户密钥,它可以作为提供者访问。

    当你打电话 Membership.GetUser() ,成员身份基础结构将调用基础提供程序并调用其 GetUser(...) 方法为其提供当前用户的键。因此,您将收到当前用户对象。

        2
  •  2
  •   Andrew Arnott    16 年前

    杰夫

    正如我在对你上述问题的评论中所说,你 必须 使用claimedidentifier作为用户名——即setAuthcookie的第一个参数。这是一个巨大的安全原因。如果您想了解更多的原因,可以在dotneopenid@googlegroups.com上启动一个线程。

    关于整个用户对象的问题…如果你想把它作为一个cookie发送下去,你必须将你的用户对象序列化为一个字符串,然后你必须以某种方式对它进行签名以防止用户篡改。您可能还想加密它。废话废话,这是一个很大的工作,你最终会得到一个巨大的cookie,在你不想要的每一个Web请求中来回移动。

    我在我的应用程序上所做的是向名为currentuser的global.asax.cs文件中添加一个静态属性,以解决您的状态问题。这样地:

    public static User CurrentUser {
        get {
            User user = HttpContext.Current.Items["CurrentUser"] as User;
            if (user == null && HttpContext.Current.User.Identity.IsAuthenticated) {
                user = Database.LookupUserByClaimedIdentifier(HttpContext.Current.User.Identity.Name);
                HttpContext.Current.Items["CurrentUser"] = user;
            }
            return user;
        }
    }
    

    注意,我将结果缓存在特定于单个HTTP请求的httpcontext.current.items字典中,并将用户回迁保持在一次命中——并且仅在页面实际需要当前用户信息时第一次回迁。

    因此,页面可以轻松获取当前登录的用户信息,如:

    User user = Global.CurrentUser;
    if (user != null) { // unnecessary check if this is a page that users must be authenticated to access
        int age = user.Age; // whatever you need here
    }
    
        3
  •  1
  •   Dale Ragan    16 年前

    一种方法是向控制器注入一个类,该类负责检索当前登录用户的信息。我就是这样做的。我创建了一个名为WebUserSession的类,它实现了一个名为iuserSession的接口。然后,在创建控制器实例时,我只使用依赖注入将其注入到控制器中。我在我的接口上实现了一个名为getcurrentuser的方法,它将返回一个用户对象,然后我可以在需要时通过将其传递给视图在我的操作中使用该对象。

    using System.Security.Principal;
    using System.Web;
    
    public interface IUserSession
    {
        User GetCurrentUser();
    }
    
    public class WebUserSession : IUserSession
    {
        public User GetCurrentUser()
        {
            IIdentity identity = HttpContext.Current.User.Identity;
            if (!identity.IsAuthenticated)
            {
                return null;
            }
    
            User currentUser = // logic to grab user by identity.Name;
            return currentUser;
        }
    }
    
    public class SomeController : Controller
    {
        private readonly IUserSession _userSession;
    
        public SomeController(IUserSession userSession)
        {
            _userSession = userSession;
        }
    
        public ActionResult Index()
        {
            User user = _userSession.GetCurrentUser();
            return View(user);
        }
    }
    

    如您所见,如果需要,现在您将有权检索用户。当然,如果愿意,可以将getcurrentuser方法更改为首先查看会话或其他方法,这样就不会一直访问数据库。