ASP.NET MVC-设置自定义身份或IPrincipal

我需要做一些相当简单的事情:在我的ASP.NET MVC应用程序中,我想设置一个自定义IIdentity/IPrincipal。以更容易/更合适的为准。我想扩展默认值,以便可以调用类似于User.Identity.IdUser.Identity.Role。没什么特别的,只是一些额外的属性

我读过大量的文章和问题,但我觉得这比实际情况更难。我想这很容易。如果用户登录,我想设置自定义身份。所以我想,我将在我的global.asax中实现应用程序\u PostAuthenticateRequest。但是,在每个请求上都会调用它,我不想在每个请求上调用数据库,这样会请求数据库中的所有数据并将其放入一个定制的IPrincipal对象中。这看起来也很不必要,速度慢,而且在错误的地方(在那里进行数据库调用),但我可能错了。或者这些数据还会从哪里来

因此,我认为,每当用户登录时,我都可以在会话中添加一些必要的变量,并将这些变量添加到应用程序\u PostAuthenticateRequest事件处理程序中的自定义IIdentity中。但是,我的Context.Session在那里是null,因此这也不是解决方法

我已经为此工作了一天,我觉得我错过了一些东西。这应该不难做到,对吧?我也有点困惑,所有(半)相关的东西,随之而来的会员资格提供者,会员资格用户角色提供者档案提供者IPPrincipal身份格式认证。。。。我是唯一一个觉得这一切都很混乱的人吗

如果有人能告诉我一个简单、优雅、高效的解决方案,在一个身份上存储一些额外的数据,而不需要所有额外的模糊。。那太好了!我知道有类似的问题,但如果我需要的答案在那里,我一定忽略了

我是这样做的

我决定使用IPrincipal而不是IIdentity,因为这意味着我不必同时实现IIdentity和IPrincipal

  1. 创建接口

    接口ICCustomPrincipal:IPPrincipal
    {
    int Id{get;set;}
    字符串名{get;set;}
    字符串LastName{get;set;}
    }
    
  2. 客户负责人

    公共类CustomPrincipal:ICustomPrincipal
    {
    公共身份标识{get;private set;}
    公共bool IsInRole(字符串角色){return false;}
    公共自定义主体(字符串电子邮件)
    {
    this.Identity=新的GenericEntity(电子邮件);
    }
    公共int Id{get;set;}
    公共字符串名{get;set;}
    公共字符串LastName{get;set;}
    }

  3. CustomPrincipalSerializeModel-用于将自定义信息序列化到FormsAuthenticationTicket对象的userdata字段中

    公共类CustomPrincipalSerializeModel
    {
    公共int Id{get;set;}
    公共字符串名{get;set;}
    公共字符串LastName{get;set;}
    }

  4. 登录方法-使用自定义信息设置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);
    返回重定向到操作(“索引”、“主页”);
    }
    
  5. 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;
    }
    }
    
  6. 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”/>
&lt/名称空间>
&lt/页面>

在视图中,您可以如下方式访问它:

@User.FirstName
@User.LastName

发表评论