Nachdem ich über Jahrzehnte verschiedene Authentifizierungs- und Autorisierungstechniken verwendet habe, verwendet meine aktuelle MVC-Anwendung die folgende Methodik.
Ansprüche werden für alle Autorisierungen verwendet. Benutzern wird eine Rolle zugewiesen (mehrere Rollen sind möglich, aber ich brauche diese nicht) - mehr unten.
Wie allgemein üblich wird eine ClaimsAuthorize-Attributklasse verwendet. Da die meisten Controller-Aktionen CRUD sind, habe ich eine Routine in der Code-First-Datenbankgenerierung, die alle Controller-Aktionen iteriert und Anspruchstypen für jedes Controller-Aktionsattribut von Lesen / Bearbeiten / Erstellen / Löschen erstellt. ZB aus,
[ClaimsAuthorize("SomeController", "Edit")]
[HttpPost]
Zur Verwendung in einer MVC-Ansicht präsentiert eine Basis-Controller-Klasse Ansichtsbeutelelemente
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
// get user claims
var user = filterContext.HttpContext.User as System.Security.Claims.ClaimsPrincipal;
if (user != null)
{
// Get all user claims on this controller. In this controler base class, [this] still gets the descendant instance type, hence name
List<Claim> claims = user.Claims.Where(c => c.Type == this.GetType().Name).ToList();
// set Viewbag with default authorisations on this controller
ViewBag.ClaimRead = claims.Any(c => c.Value == "Read");
ViewBag.ClaimEdit = claims.Any(c => c.Value == "Edit");
ViewBag.ClaimCreate = claims.Any(c => c.Value == "Create");
ViewBag.ClaimDelete = claims.Any(c => c.Value == "Delete");
}
base.OnActionExecuting(filterContext);
}
Für Website-Menüs und andere Nicht-Controller-Aktionen habe ich andere Ansprüche. ZB ob ein Benutzer ein bestimmtes Geldfeld anzeigen kann.
bool UserHasSpecificClaim(string claimType, string claimValue)
{
// get user claims
var user = this.HttpContext.User as System.Security.Claims.ClaimsPrincipal;
if (user != null)
{
// Get the specific claim if any
return user.Claims.Any(c => c.Type == claimType && c.Value == claimValue);
}
return false;
}
public bool UserHasTradePricesReadClaim
{
get
{
return UserHasSpecificClaim("TradePrices", "Read");
}
}
Wo passen also Rollen hin?
Ich habe eine Tabelle, die eine Rolle mit einem (Standard-) Satz von Ansprüchen verknüpft. Beim Festlegen der Benutzerberechtigung wird dem Benutzer standardmäßig die Ansprüche seiner Rolle mitgeteilt. Jeder Benutzer kann mehr oder weniger Ansprüche als die Standardansprüche haben. Um die Bearbeitung zu vereinfachen, wird die Anspruchsliste nach Controller und Aktionen (in einer Reihe) angezeigt, wobei andere Ansprüche aufgelistet werden. Schaltflächen werden mit etwas Javascript verwendet, um eine Reihe von Aktionen auszuwählen, um das "Klicken" zu minimieren, das zum Auswählen von Ansprüchen erforderlich ist. Beim Speichern werden die Ansprüche des Benutzers gelöscht und alle ausgewählten Ansprüche hinzugefügt. Die Webanwendung lädt Ansprüche nur einmal, sodass Änderungen zu einem erneuten Laden dieser statischen Daten führen müssen.
Manager können daher auswählen, welche Ansprüche in jeder Rolle enthalten sind und welche Ansprüche ein Benutzer hat, nachdem er sie auf eine Rolle und diese Standardansprüche festgelegt hat. Das System hat nur eine geringe Anzahl von Benutzern, sodass die Verwaltung dieser Daten unkompliziert ist