如何在MVC5中获取当前登录用户的特定字段?

我有一个使用个人身份validation的MVC5应用程序,当然还有ASP.NET身份。 关键是我扩展了我有一个inheritance自ApplicationUser的模型,它的定义如下:

public class NormalUser : ApplicationUser { public string FirstName { get; set; } public string LastName { get; set; } } 

所以,重点是,首先我要检查是否有登录用户,如果有,我想获得他/她的FirstName,LastName和Email字段。 我怎样才能实现它?

我想我需要使用这样的东西来检查是否有登录用户:

 if (Request.IsAuthenticated) { ... } 

但是,如何为当前用户获取这些特定字段的值?

是的,在Identity中,如果您需要其他用户信息,只需从数据库中提取用户,因为现在所有用户都存储在实际用户对象中。

 if (Request.IsAuthenticated) { var user = UserManager.FindById(User.Identity.GetUserId()); } 

如果GetUserId不在User.Identity ,请将以下内容添加到您的使用中:

 using Microsoft.AspNet.Identity; 

在MVC5中,用户数据默认存储在会话中,并根据请求将数据解析为包含用户名(或id)和声明的ClaimsPrincipal

这是我选择实现它的方式,它可能不是最简单的解决方案,但它确实使它易于使用。

用法示例:

在控制器中:

 public ActionResult Index() { ViewBag.ReverseDisplayName = this.User.LastName + ", " + this.User.FirstName; } 

在视图中或_Layout:

 @if(User.IsAuthenticated) { @User.DisplayName } 

1.替换ClaimsIdentityFactory

 using System.Security.Claims; using System.Threading.Tasks; using Domain.Models; using Microsoft.AspNet.Identity; public class AppClaimsIdentityFactory : IClaimsIdentityFactory { internal const string IdentityProviderClaimType = "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider"; internal const string DefaultIdentityProviderClaimValue = "My Identity Provider"; ///  /// Constructor ///  public AppClaimsIdentityFactory() { RoleClaimType = ClaimsIdentity.DefaultRoleClaimType; UserIdClaimType = ClaimTypes.NameIdentifier; UserNameClaimType = ClaimsIdentity.DefaultNameClaimType; SecurityStampClaimType = Constants.DefaultSecurityStampClaimType; } ///  /// Claim type used for role claims ///  public string RoleClaimType { get; set; } ///  /// Claim type used for the user name ///  public string UserNameClaimType { get; set; } ///  /// Claim type used for the user id ///  public string UserIdClaimType { get; set; } ///  /// Claim type used for the user security stamp ///  public string SecurityStampClaimType { get; set; } ///  /// Create a ClaimsIdentity from a user ///  ///  ///  ///  ///  public virtual async Task CreateAsync(UserManager manager, User user, string authenticationType) { if (manager == null) { throw new ArgumentNullException("manager"); } if (user == null) { throw new ArgumentNullException("user"); } var id = new ClaimsIdentity(authenticationType, UserNameClaimType, RoleClaimType); id.AddClaim(new Claim(UserIdClaimType, user.Id.ToString(), ClaimValueTypes.String)); id.AddClaim(new Claim(UserNameClaimType, user.UserName, ClaimValueTypes.String)); id.AddClaim(new Claim(IdentityProviderClaimType, DefaultIdentityProviderClaimValue, ClaimValueTypes.String)); id.AddClaim(new Claim(ClaimTypes.Email, user.EmailAddress)); if (user.ContactInfo.FirstName != null && user.ContactInfo.LastName != null) { id.AddClaim(new Claim(ClaimTypes.GivenName, user.ContactInfo.FirstName)); id.AddClaim(new Claim(ClaimTypes.Surname, user.ContactInfo.LastName)); } if (manager.SupportsUserSecurityStamp) { id.AddClaim(new Claim(SecurityStampClaimType, await manager.GetSecurityStampAsync(user.Id))); } if (manager.SupportsUserRole) { user.Roles.ToList().ForEach(r => id.AddClaim(new Claim(ClaimTypes.Role, r.Id.ToString(), ClaimValueTypes.String))); } if (manager.SupportsUserClaim) { id.AddClaims(await manager.GetClaimsAsync(user.Id)); } return id; } 

2.更改UserManager以使用它

 public static UserManager Create(IdentityFactoryOptions options, IOwinContext context) { var manager = new UserManager(new UserStore(new ApplicationDbContext())) { ClaimsIdentityFactory = new AppClaimsIdentityFactory() }; // more initialization here return manager; } 

3.创建新的自定义Principal

 using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Security.Claims; public class UserPrincipal : ClaimsPrincipal { public UserPrincipal(ClaimsPrincipal principal) : base(principal.Identities) { } public int UserId { get { return FindFirstValue(ClaimTypes.NameIdentifier); } } public string UserName { get { return FindFirstValue(ClaimsIdentity.DefaultNameClaimType); } } public string Email { get { return FindFirstValue(ClaimTypes.Email); } } public string FirstName { get { return FindFirstValue(ClaimTypes.GivenName); } } public string LastName { get { return FindFirstValue(ClaimTypes.Surname); } } public string DisplayName { get { var name = string.Format("{0} {1}", this.FirstName, this.LastName).Trim(); return name.Length > 0 ? name : this.UserName; } } public IEnumerable Roles { get { return FindValues(ClaimTypes.Role); } } private T FindFirstValue(string type) { return Claims .Where(p => p.Type == type) .Select(p => (T)Convert.ChangeType(p.Value, typeof(T), CultureInfo.InvariantCulture)) .FirstOrDefault(); } private IEnumerable FindValues(string type) { return Claims .Where(p => p.Type == type) .Select(p => (T)Convert.ChangeType(p.Value, typeof(T), CultureInfo.InvariantCulture)) .ToList(); } } 

4.创建AuthenticationFilter以使用它

 using System.Security.Claims; using System.Web.Mvc; using System.Web.Mvc.Filters; public class AppAuthenticationFilterAttribute : ActionFilterAttribute, IAuthenticationFilter { public void OnAuthentication(AuthenticationContext filterContext) { //This method is responsible for setting and modifying the principle for the current request though the filterContext . //Here you can modify the principle or applying some authentication logic. var principal = filterContext.Principal as ClaimsPrincipal; if (principal != null && !(principal is UserPrincipal)) { filterContext.Principal = new UserPrincipal(principal); } } public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext) { //This method is responsible for validating the current principal and permitting the execution of the current action/request. //Here you should validate if the current principle is valid / permitted to invoke the current action. (However I would place this logic to an authorization filter) //filterContext.Result = new RedirectToRouteResult("CustomErrorPage",null); } } 

5.注册authfilter以在FilterConfig全局加载

 public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); filters.Add(new AppAuthenticationFilterAttribute()); } 

到目前为止, Principal是持久的,我们剩下要做的就是在Controller和View中公开它。

6.创建控制器基类

 public abstract class ControllerBase : Controller { public new UserPrincipal User { get { return HttpContext.User as UserPrincipal; } } } 

7.创建WebViewPage基类并修改web.config以使用它

 public abstract class BaseViewPage : WebViewPage { public virtual new UserPrincipal User { get { return base.User as UserPrincipal; } } public bool IsAuthenticated { get { return base.User.Identity.IsAuthenticated; } } } public abstract class BaseViewPage : WebViewPage { public virtual new UserPrincipal User { get { return base.User as UserPrincipal; } } public bool IsAuthenticated { get { return base.User.Identity.IsAuthenticated; } } } 

Views文件夹中的web.config

  

重要!

不要在Principal上存储太多数据,因为这些数据是在每个请求上来回传递的。