我需要做一些相当简单的事情:在我的ASP.NET MVC应用程序中,我想设置一个自定义IIdentity/IPrincipal。以更容易/更合适的为准。我想扩展默认值,以便可以调用类似于User.Identity.Id
和User.Identity.Role
。没什么特别的,只是一些额外的属性
我读过大量的文章和问题,但我觉得这比实际情况更难。我想这很容易。如果用户登录,我想设置自定义身份。所以我想,我将在我的global.asax中实现应用程序\u PostAuthenticateRequest
。但是,在每个请求上都会调用它,我不想在每个请求上调用数据库,这样会请求数据库中的所有数据并将其放入一个定制的IPrincipal对象中。这看起来也很不必要,速度慢,而且在错误的地方(在那里进行数据库调用),但我可能错了。或者这些数据还会从哪里来
因此,我认为,每当用户登录时,我都可以在会话中添加一些必要的变量,并将这些变量添加到应用程序\u PostAuthenticateRequest
事件处理程序中的自定义IIdentity中。但是,我的Context.Session
在那里是null
,因此这也不是解决方法
我已经为此工作了一天,我觉得我错过了一些东西。这应该不难做到,对吧?我也有点困惑,所有(半)相关的东西,随之而来的会员资格提供者,会员资格用户
,角色提供者
,档案提供者
,IPPrincipal
,身份
,格式认证
。。。。我是唯一一个觉得这一切都很混乱的人吗
如果有人能告诉我一个简单、优雅、高效的解决方案,在一个身份上存储一些额外的数据,而不需要所有额外的模糊。。那太好了!我知道有类似的问题,但如果我需要的答案在那里,我一定忽略了
我是这样做的
我决定使用IPrincipal而不是IIdentity,因为这意味着我不必同时实现IIdentity和IPrincipal
-
创建接口
接口ICCustomPrincipal:IPPrincipal { int Id{get;set;} 字符串名{get;set;} 字符串LastName{get;set;} }
-
客户负责人
公共类CustomPrincipal:ICustomPrincipal
{
公共身份标识{get;private set;}
公共bool IsInRole(字符串角色){return false;}
公共自定义主体(字符串电子邮件)
{
this.Identity=新的GenericEntity(电子邮件);
}
公共int Id{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
}
-
CustomPrincipalSerializeModel-用于将自定义信息序列化到FormsAuthenticationTicket对象的userdata字段中
公共类CustomPrincipalSerializeModel
{
公共int Id{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
}
-
登录方法-使用自定义信息设置cookie
if(Membership.ValidateUser(viewModel.Email,viewModel.Password)) { var user=userRepository.Users.Where(u=>;u.Email==viewModel.Email).First(); CustomPrincipalSerializeModel serializeModel=新的CustomPrincipalSerializeModel(); serializeModel.Id=user.Id; serializeModel.FirstName=user.FirstName; serializeModel.LastName=user.LastName; JavaScriptSerializer serializer=新的JavaScriptSerializer(); string userData=serializer.Serialize(serializeModel); FormsAuthenticationTicket authTicket=新的FormsAuthenticationTicket( 1. viewModel.Email, 日期时间,现在, DateTime.Now.AddMinutes(15), 错误的 用户数据); 字符串encTicket=FormsAuthentication.Encrypt(authTicket); HttpCookie faCookie=新的HttpCookie(FormsAuthentication.formscookeName,encTicket); 响应.Cookies.添加(faCookie); 返回重定向到操作(“索引”、“主页”); }
-
Global.asax.cs-读取cookie并替换HttpContext.User对象,这是通过重写PostAuthenticateRequest完成的
受保护的无效应用程序\u PostAuthenticateRequest(对象发送方,事件参数e) { HttpCookie authCookie=Request.Cookies[FormsAuthentication.formscookeName]; if(authCookie!=null) { FormsAuthenticationTicket authTicket=FormsAuthentication.Decrypt(authCookie.Value); JavaScriptSerializer serializer=新的JavaScriptSerializer(); CustomPrincipalSerializeModel serializeModel=serializer.Deserialize<;CustomPrincipalSerializeModel>;(authTicket.UserData); CustomPrincipal newUser=newcustomprincipal(authTicket.Name); newUser.Id=serializeModel.Id; newUser.FirstName=serializeModel.FirstName; newUser.LastName=serializeModel.LastName; HttpContext.Current.User=newUser; } }
-
Razor视图中的访问
@((用户作为CustomPrincipal.Id) @((用户作为CustomPrincipal).FirstName) @((用户作为CustomPrincipal).LastName)
在代码中:
(用户作为CustomPrincipal).Id
(用户作为CustomPrincipal)。名字
(用户作为CustomPrincipal)。LastName
我认为代码是不言自明的。如果不是,请告诉我
此外,为了使访问更容易,您可以创建一个基本控制器并覆盖返回的用户对象(HttpContext.User):
公共类BaseController:控制器
{
受保护的虚拟新CustomPrincipal用户
{
获取{返回HttpContext.User作为CustomPrincipal;}
}
}
然后,对于每个控制器:
公共类AccountController:BaseController
{
// …
}
这将允许您访问代码中的自定义字段,如下所示:
User.Id
User.FirstName
User.LastName
但这在内部视图中不起作用。为此,您需要创建自定义WebViewPage实现:
公共抽象类BaseViewPage:WebViewPage
{
公共虚拟新用户
{
获取{return base.User as CustomPrincipal;}
}
}
公共抽象类BaseViewPage<;TModel>;:WebViewPage<;TModel>;
{
公共虚拟新用户
{
获取{return base.User as CustomPrincipal;}
}
}
在Views/web.config中将其设为默认页面类型:
<;pages pageBaseType=“Your.Namespace.BaseViewPage”>;
<;名称空间>;
<;添加namespace=“System.Web.Mvc”/>;
<;添加namespace=“System.Web.Mvc.Ajax”/>;
<;添加namespace=“System.Web.Mvc.Html”/>;
<;添加namespace=“System.Web.Routing”/>;
</名称空间>;
</页面>;
在视图中,您可以如下方式访问它:
@User.FirstName
@User.LastName