2014-09-08 12 views
5

Ich habe eine MVC5-Anwendung, die individuelle Authentifizierung und natürlich ASP.NET-Identität verwendet. Der Punkt ist, dass ich verlängert hatte ich ein Modell, das von ApplicationUser erbt, wird es einfach wie folgt definiert:Wie bekomme ich die spezifischen Felder des aktuell angemeldeten Benutzers in MVC5?

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

So ist der Punkt, dass zunächst alles, was ich überprüfen möchten, ob ein eingeloggten ist in Benutzer, und wenn es gibt, möchte ich seine/ihre Vorname, Nachname und E-Mail-Felder erhalten. Wie kann ich es erreichen?

Ich glaube, ich brauche etwas zu, um zu überprüfen, ob ein angemeldeter Benutzer:

if (Request.IsAuthenticated) 
{ 
    ... 
} 

Aber, wie kann ich diese spezifischen Felder Werte für den aktuellen Benutzer erhalten?

+0

können Sie keinen Code verwenden oder implementieren, der 'PrincipalContext' verwendet – MethodMan

+0

@DJKRAZE Keine Ahnung. – tett

+0

es ist sehr einfach zu bedienen und Sie können an den Benutzernamen über athe samAccount gibt es viele Beispiele tatsächlich .. wenn der Benutzer startet die Seite oder Website können Sie leicht zu dieser Information – MethodMan

Antwort

2

Ja, in Identity, wenn Sie zusätzliche Benutzerinformationen benötigen, ziehen Sie einfach den Benutzer aus der Datenbank, da dies alles auf dem aktuellen Benutzerobjekt gespeichert ist.

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

Wenn GetUserId nicht auf User.Identity ist, fügen Sie folgendes zu Ihrem usings:

using Microsoft.AspNet.Identity; 
+0

Um die Daten jedes Mal aus der DB zu holen, wenn Sie den Vor- und Nachnamen des Benutzers benötigen, scheint das sehr ineffizient zu sein. –

+0

Das funktioniert ganz gut für die E-Mail, aber nicht für die FirstName und LastName Felder. Mit dem oben genannten kann ich nur die Standard-ApplicationUser-Felder erhalten, nicht die Felder, die ich später hinzugefügt habe. – tett

+1

Oh, du sprichst von der Unterklasse. Nun, wenn Sie 'UserManager' instanziieren, müssen Sie die Benutzerklasse angeben, die verwendet werden soll. Sie verwenden wahrscheinlich nur den Standardwert 'UserManager ', der nur' ApplicationUser'-Instanzen zurückgibt, die nicht die Eigenschaften 'FirstName' und' LastName' haben. Sie können entweder 'UserManager ' instanziieren oder Ihren Kontext direkt über 'context.Users.OfType .Find (User.Identity.GetUserId())' –

7

In MVC5 die Benutzerdaten standardmäßig in der Sitzung gespeichert und auf Wunsch werden die Daten in ein analysiert ClaimsPrincipal enthält den Benutzernamen (oder die ID) und die Ansprüche.

Dies ist die Art, wie ich es implementiert habe, es ist vielleicht nicht die einfachste Lösung, aber es macht es auf jeden Fall einfach zu bedienen.

Anwendungsbeispiel:

In Controller:

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

Im Hinblick oder _Layout:

@if(User.IsAuthenticated) 
{ 
    <span>@User.DisplayName</span> 
} 

1. Ersetzen ClaimsIdentityFactory

using System.Security.Claims; 
using System.Threading.Tasks; 
using Domain.Models; 
using Microsoft.AspNet.Identity; 

public class AppClaimsIdentityFactory : IClaimsIdentityFactory<User, int> 
{ 
    internal const string IdentityProviderClaimType = "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider"; 

    internal const string DefaultIdentityProviderClaimValue = "My Identity Provider"; 

    /// <summary> 
    ///  Constructor 
    /// </summary> 
    public AppClaimsIdentityFactory() 
    { 
     RoleClaimType = ClaimsIdentity.DefaultRoleClaimType; 
     UserIdClaimType = ClaimTypes.NameIdentifier; 
     UserNameClaimType = ClaimsIdentity.DefaultNameClaimType; 
     SecurityStampClaimType = Constants.DefaultSecurityStampClaimType; 
    } 

    /// <summary> 
    ///  Claim type used for role claims 
    /// </summary> 
    public string RoleClaimType { get; set; } 

    /// <summary> 
    ///  Claim type used for the user name 
    /// </summary> 
    public string UserNameClaimType { get; set; } 

    /// <summary> 
    ///  Claim type used for the user id 
    /// </summary> 
    public string UserIdClaimType { get; set; } 

    /// <summary> 
    ///  Claim type used for the user security stamp 
    /// </summary> 
    public string SecurityStampClaimType { get; set; } 

    /// <summary> 
    ///  Create a ClaimsIdentity from a user 
    /// </summary> 
    /// <param name="manager"></param> 
    /// <param name="user"></param> 
    /// <param name="authenticationType"></param> 
    /// <returns></returns> 
    public virtual async Task<ClaimsIdentity> CreateAsync(UserManager<User, int> 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. Ändern Sie den UserManager verwenden, um es

public static UserManager<User,int> Create(IdentityFactoryOptions<AppUserManager> options, IOwinContext context) 
{ 
    var manager = new UserManager<User,int>(new UserStore<User,int>(new ApplicationDbContext())) 
    { 
     ClaimsIdentityFactory = new AppClaimsIdentityFactory() 
    }; 

    // more initialization here 

    return manager; 
} 

3. Erstellen Sie eine neue benutzerdefinierte 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<int>(ClaimTypes.NameIdentifier); } 
    } 

    public string UserName 
    { 
     get { return FindFirstValue<string>(ClaimsIdentity.DefaultNameClaimType); } 
    } 

    public string Email 
    { 
     get { return FindFirstValue<string>(ClaimTypes.Email); } 
    } 

    public string FirstName 
    { 
     get { return FindFirstValue<string>(ClaimTypes.GivenName); } 
    } 

    public string LastName 
    { 
     get { return FindFirstValue<string>(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<int> Roles 
    { 
     get { return FindValues<int>(ClaimTypes.Role); } 
    } 

    private T FindFirstValue<T>(string type) 
    { 
     return Claims 
      .Where(p => p.Type == type) 
      .Select(p => (T)Convert.ChangeType(p.Value, typeof(T), CultureInfo.InvariantCulture)) 
      .FirstOrDefault(); 
    } 

    private IEnumerable<T> FindValues<T>(string type) 
    { 
     return Claims 
      .Where(p => p.Type == type) 
      .Select(p => (T)Convert.ChangeType(p.Value, typeof(T), CultureInfo.InvariantCulture)) 
      .ToList(); 
    } 
} 

4. eine AuthenticationFilter erstellen, es zu benutzen

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.Registrieren Sie den Auth Filter global in der FilterConfig

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

laden Inzwischen die Principal beibehalten wird und alles, was wir tun müssen, ist aussetzen im Controller und Ansicht.

6. Erstellen Sie eine Controller-Basisklasse

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

7. Erstellen Sie eine WebViewPage Basisklasse und ändern Sie die web.config, es zu benutzen

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<TModel> : WebViewPage<TModel> 
{ 
    public virtual new UserPrincipal User 
    { 
     get { return base.User as UserPrincipal; } 
    } 

    public bool IsAuthenticated 
    { 
     get { return base.User.Identity.IsAuthenticated; } 
    } 
} 

Und die web.config innerhalb des Views Ordner :

<pages pageBaseType="MyApp.Web.Views.BaseViewPage"> 

Wichtig!

Speichern Sie nicht zu viele Daten auf dem Principal, da diese Daten bei jeder Anforderung hin und her übergeben werden.

+1

(nicht Ihre Schuld) Dies ist verrückt, was MS dachte? Güte. – toddmo

Verwandte Themen