我需要做一些相当简单的事情:在我的ASP。NET MVC应用程序,我想设置自定义IIdentity / IPrincipal。哪一个更容易/更合适。我想扩展默认值,这样我就可以调用User.Identity.Id和User.Identity.Role之类的东西。没什么特别的,只是一些额外的属性。
I've read tons of articles and questions but I feel like I'm making it harder than it actually is. I thought it would be easy. If a user logs on, I want to set a custom IIdentity. So I thought, I will implement Application_PostAuthenticateRequest in my global.asax. However, that is called on every request, and I don't want to do a call to the database on every request which would request all the data from the database and put in a custom IPrincipal object. That also seems very unnecessary, slow, and in the wrong place (doing database calls there) but I could be wrong. Or where else would that data come from?
因此,我认为,每当用户登录时,我都可以在会话中添加一些必要的变量,这些变量将添加到Application_PostAuthenticateRequest事件处理程序中的自定义IIdentity中。然而,我的上下文。Session在那里是空的,所以这也不是正确的方法。
我已经为此工作了一天了,我觉得我遗漏了一些东西。这应该不难,对吧?我也对随之而来的所有(半)相关的东西感到困惑。MembershipProvider, MembershipUser, RoleProvider, ProfileProvider, IPrincipal, IIdentity, FormsAuthentication....难道只有我一个人对这一切感到困惑吗?
如果有人能告诉我一个简单,优雅,高效的解决方案来存储一些额外的数据在IIdentity没有所有额外的模糊。那太好了!我知道在SO上有类似的问题,但如果我需要的答案在那里,我一定是忽略了。
下面是一个完成这项工作的例子。bool isValid是通过查看一些数据存储(假设您的用户数据库)来设置的。UserID只是我维护的一个ID。您可以向用户数据添加其他信息,如电子邮件地址。
protected void btnLogin_Click(object sender, EventArgs e)
{
//Hard Coded for the moment
bool isValid=true;
if (isValid)
{
string userData = String.Empty;
userData = userData + "UserID=" + userID;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, username, DateTime.Now, DateTime.Now.AddMinutes(30), true, userData);
string encTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
Response.Cookies.Add(faCookie);
//And send the user where they were heading
string redirectUrl = FormsAuthentication.GetRedirectUrl(username, false);
Response.Redirect(redirectUrl);
}
}
在全局asax中添加以下代码来检索您的信息
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Request.Cookies[
FormsAuthentication.FormsCookieName];
if(authCookie != null)
{
//Extract the forms authentication cookie
FormsAuthenticationTicket authTicket =
FormsAuthentication.Decrypt(authCookie.Value);
// Create an Identity object
//CustomIdentity implements System.Web.Security.IIdentity
CustomIdentity id = GetUserIdentity(authTicket.Name);
//CustomPrincipal implements System.Web.Security.IPrincipal
CustomPrincipal newUser = new CustomPrincipal();
Context.User = newUser;
}
}
稍后使用该信息时,可以按如下方式访问自定义主体。
(CustomPrincipal)this.User
or
(CustomPrincipal)this.Context.User
这将允许您访问自定义用户信息。
下面是一个完成这项工作的例子。bool isValid是通过查看一些数据存储(假设您的用户数据库)来设置的。UserID只是我维护的一个ID。您可以向用户数据添加其他信息,如电子邮件地址。
protected void btnLogin_Click(object sender, EventArgs e)
{
//Hard Coded for the moment
bool isValid=true;
if (isValid)
{
string userData = String.Empty;
userData = userData + "UserID=" + userID;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, username, DateTime.Now, DateTime.Now.AddMinutes(30), true, userData);
string encTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
Response.Cookies.Add(faCookie);
//And send the user where they were heading
string redirectUrl = FormsAuthentication.GetRedirectUrl(username, false);
Response.Redirect(redirectUrl);
}
}
在全局asax中添加以下代码来检索您的信息
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Request.Cookies[
FormsAuthentication.FormsCookieName];
if(authCookie != null)
{
//Extract the forms authentication cookie
FormsAuthenticationTicket authTicket =
FormsAuthentication.Decrypt(authCookie.Value);
// Create an Identity object
//CustomIdentity implements System.Web.Security.IIdentity
CustomIdentity id = GetUserIdentity(authTicket.Name);
//CustomPrincipal implements System.Web.Security.IPrincipal
CustomPrincipal newUser = new CustomPrincipal();
Context.User = newUser;
}
}
稍后使用该信息时,可以按如下方式访问自定义主体。
(CustomPrincipal)this.User
or
(CustomPrincipal)this.Context.User
这将允许您访问自定义用户信息。
作为Web表单用户(不是MVC)的LukeP代码的补充,如果你想简化页面背后代码的访问,只需将下面的代码添加到一个基础页面,并在所有页面中派生基础页面:
Public Overridable Shadows ReadOnly Property User() As CustomPrincipal
Get
Return DirectCast(MyBase.User, CustomPrincipal)
End Get
End Property
所以在你的代码后面,你可以简单地访问:
User.FirstName or User.LastName
我在Web表单场景中缺失的是如何在代码中获得相同的行为,而不是绑定到页面,例如在httpmodules中,我应该总是在每个类中添加一个类型转换,还是有更聪明的方法来获得这个?
感谢你的回答,感谢LukeP,因为我使用了你的例子作为我的自定义用户的基础(现在有user。角色、用户。Tasks, User.HasPath(int), User.Settings.Timeout和其他很多不错的东西)
在LukeP回答的基础上,结合Web.config,增加了设置超时和requireSSL的方法。
参考资料链接
MSDN,解释:表单认证在ASP。NET 2.0
MSDN, FormsAuthentication类
所以,.net Access Forms认证的“timeout”值在代码中
LukeP代码修改
1、根据Web.Config设置超时时间。FormsAuthentication。Timeout将获得Timeout值,该值在web.config中定义。我将以下内容包装为一个函数,该函数返回一张票据。
int version = 1;
DateTime now = DateTime.Now;
// respect to the `timeout` in Web.config.
TimeSpan timeout = FormsAuthentication.Timeout;
DateTime expire = now.Add(timeout);
bool isPersist = false;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
version,
name,
now,
expire,
isPersist,
userData);
2、根据RequireSSL配置,配置cookie是否安全。
HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
// respect to `RequreSSL` in `Web.Config`
bool bSSL = FormsAuthentication.RequireSSL;
faCookie.Secure = bSSL;