基本上,我使用OpenId登录我的网站,非常类似于我所假设的那样。当我收到信息后,我把它扔进一个数据库并创建我的“注册用户”。我设置了AuthCookie:
FormsAuthentication.SetAuthCookie(user.Profile.MyProfile.DisplayName, false);
然后我可以将它用作用户名。但是,我想传入整个对象而不仅仅是显示名称的字符串。所以我的问题是:
SO如何做到这一点?
他们是否会扩展/覆盖SetAuthCookie(string, bool)
方法以接受用户对象,即SetAuthCookie(User(object), bool)
。
保留User对象的最佳方法是什么,以便我的Web应用程序的每个页面上的UserControl都可以使用它?
提前致谢!
答案 0 :(得分:3)
您可以通过implementing自定义Membership Provider或扩展现有的MembershipUser来实现此行为。提供程序根据密钥(或仅通过用户名)存储用户信息,并提供对{{3}}类的访问权限,您可以根据需要进行扩展。因此,当您致电FormsAuthentication.SetAuthCookie(...)
时,您基本上设置了用户密钥,可以通过提供商进行访问。
当您致电Membership.GetUser()
时,会员基础设施将调用基础提供商并调用其GetUser(...)
方法,为其提供当前用户的密钥。因此,您将收到当前的用户对象。
答案 1 :(得分:2)
杰夫,
正如我在上述问题的评论中所说,必须使用ClaimedIdentifier作为用户名 - 也就是SetAuthCookie的第一个参数。这有一个巨大的安全原因。如果您想了解更多有关原因的信息,请随时在dotnetopenid@googlegroups.com上发布主题。
现在关于整个用户对象的问题...如果你想把它作为一个cookie发送,你必须将你的用户对象序列化为字符串,然后你必须以某种方式签名防止用户篡改。您可能还想加密它。 Blah blah,这是一项很多工作,你最终会得到一个大的cookie来回传递你不想要的每个网页请求。
我在我的应用上为解决您所述的问题所做的是在我的Global.asax.cs文件中添加一个名为CurrentUser的静态属性。像这样:
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;
}
}
注意我将结果缓存在HttpContext.Current.Items字典中,该字典特定于单个HTTP请求,并且将用户提取保持为单次命中 - 并且仅在页面实际需要时才第一次获取它CurrentUser信息。
因此,页面可以轻松获取当前登录的用户信息,如下所示:
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
}
答案 2 :(得分:1)
一种方法是向控制器注入一个类,该类负责检索当前登录用户的信息。我就是这样做的。我创建了一个名为WebUserSession的类,它实现了一个名为IUserSession的接口。然后我在创建控制器实例时使用依赖注入将其注入控制器。我在我的接口上实现了一个名为GetCurrentUser的方法,它将返回一个User对象,然后我可以根据需要将其用于我的操作中,方法是将其传递给视图。
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方法,以便首先查看会话或其他一些方法(如果您愿意),这样您就不会一直访问数据库。