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.
können Sie keinen Code verwenden oder implementieren, der 'PrincipalContext' verwendet – MethodMan
@DJKRAZE Keine Ahnung. – tett
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