Nachdem Sie Ihr Web-API entwickelt haben, müssen Sie, bevor Sie es Ihren Kunden zur Verfügung stellen, je nach Ihren Anforderungen einige oder alle Teile Ihres API-Services sichern, damit nur geprüfte Benutzer auf Ihren API-Service zugreifen können. Diese Sicherung in ASP.NET kann mithilfe der Authentifizierungs- und Autorisierungsmechanismen erreicht werden.
Authentifizierung ist der Prozess der Feststellung, ob jemand oder etwas tatsächlich wer oder was ist. Durch die Verwendung des Authentifizierungsmechanismus stellen wir sicher, dass jede vom Web-API-Dienst empfangene Anforderung von einem Client mit den richtigen Anmeldeinformationen gesendet wird.
EIN Nachrichtenhandler ist eine Klasse, die eine HTTP-Anforderung empfängt und eine HTTP-Antwort zurückgibt. Message-Handler sind abgeleitete Klassen von der abstrakten Klasse HttpMessageHandler
. Sie sind gut für Querschnittsprobleme, die auf der Ebene von HTTP-Nachrichten arbeiten (und nicht auf Controller-Aktionen). Ein Message-Handler könnte beispielsweise Folgendes tun:
In einer Web-API werden normalerweise eine Reihe von Meldungshandlern miteinander verkettet, wodurch ein Muster gebildet wird Delegieren Handler.
Die Reihenfolge, in der diese Handler eingerichtet werden, ist wichtig, da sie sequentiell ausgeführt werden.
Der wichtigste Handler befindet sich ganz oben und bewacht alles, was hereinkommt. Wenn die Schecks bestanden werden, leitet er diese Anforderung in der Kette an den nächsten delegierenden Handler weiter und so weiter.
Wenn alles gut geht, kommt er beim API-Controller an und führt die gewünschte Aktion aus. Wenn jedoch eine der Prüfungen innerhalb der Handler fehlschlägt, wird die Anforderung abgelehnt und eine Antwort an den Client gesendet.
Mit so viel Theorie in der Hand schreiben wir jetzt Code für unsere Handler. In diesem Artikel werden zwei Meldungshandler erstellt:
Erstellen Sie in Ihrem Web-API-Projekt einen Ordner mit dem Namen MessageHandlers
und füge eine Klasse hinzu APIKeyHandler.cs
.
public class APIKeyHandler: DelegatingHandler // Setzt einen Standard-API-Schlüssel für private const-Zeichenfolge yourApiKey = "X-some-key"; Geschützte Außerkraftsetzung async TaskSendAsync (Anforderung HttpRequestMessage, AnnullationToken-Annullierungstoken) bool isValidAPIKey = false; IEnumerable lsHeaders; // Überprüfen Sie, ob der API-Schlüssel vorhanden ist. Var checkApiKeyExists = request.Headers.TryGetValues ("API_KEY", out lsHeaders); if (checkApiKeyExists) if (lsHeaders.FirstOrDefault (). Equals (IhrApiKey)) isValidAPIKey = true; // Wenn der Schlüssel nicht gültig ist, geben Sie einen http-Statuscode zurück. if (! isValidAPIKey) Rückgabeanforderung.CreateResponse (HttpStatusCode.Forbidden, "Bad API Key"); // Zulassen, dass die Anforderung in der Pipeline weiter verarbeitet wird var response = await base.SendAsync (request, cancelToken); // Antwort zurücksenden, Kette sichern Antwort zurücksetzen;
Das APIKeyHandler.cs
erbt von DelegatingHandler
, die wiederum von erbt HttpMessageHandler
. Dies ermöglicht es uns, die Funktionalität zum Überprüfen einer HTTP-Anforderung zu überschreiben und zu steuern, ob diese Anforderung durch die Pipeline zum nächsten Handler und Controller weitergeleitet werden soll, oder die Anforderung durch Senden einer benutzerdefinierten Antwort zu stoppen.
In dieser Klasse erreichen wir dies, indem Sie das überschreiben SendAsync
Methode. Diese Methode sucht nach einem API-Schlüssel (API-SCHLÜSSEL
) im Header jeder HTTP-Anforderung und leitet die Anforderung nur an den Controller weiter, wenn im Anforderungsheader ein gültiger API-Schlüssel vorhanden ist.
Um diesen Handler in Aktion zu sehen, müssen wir ihn zunächst in unserer Anwendung im registrieren Anwendungsstart
Methode aus der Global.asax
Datei.
GlobalConfiguration.Configuration.MessageHandlers.Add (new APIKeyHandler ());
Versuchen Sie, eine beliebige Methode aufzurufen, die Sie über Ihre Web-API-Controller verfügbar gemacht haben. Als Antwort sollte "Bad API Key" angezeigt werden.
Für eine Demo in diesem Artikel verwende ich dasselbe Projekt und die URLs, die ich in meinem vorherigen Artikel "Entwickeln einer ASP.NET-Web-API" erstellt habe..
Lassen Sie uns das überprüfen APIKeyHandler
funktioniert in Ordnung, indem Sie eine HTTP-Anfrage mit korrekten Kopfzeilen erstellen. Dafür müssen wir einen HTTP-Header mit dem Schlüsselwert erstellen:
"API_KEY": "X-Some-Key"
Ich verwende ein Mozilla-Browser-Plugin namens "HTTP-Tool", um hier HTTP-Anforderungsheader zu erstellen.
Die HTTP-Anforderung wird nun vom Handler vollständig an den Controller übergeben.
Unser API-Schlüsselprüfungshandler ist jetzt installiert. Dies sichert unsere Web-API, um sicherzustellen, dass nur die Clients, die über gültige API-Schlüssel verfügen, auf diesen Dienst zugreifen können. Als Nächstes werden wir untersuchen, wie wir Sicherheit basierend auf Benutzerrollen implementieren können.
Die Standardauthentifizierung ist, wie der Name schon sagt, die einfachste und grundlegendste Form der Authentifizierung von HTTP-Anforderungen. Der Client sendet Base64-codierte Anmeldeinformationen im Authorize-Header bei jeder HTTP-Anforderung. Wenn die Anmeldeinformationen überprüft wurden, gibt die API die erwartete Antwort zurück. Für die Standardauthentifizierung ist keine serverseitige Sitzungsspeicherung oder Implementierung von Cookies erforderlich, da jede Anforderung von der API überprüft wird.
Sobald die grundlegende Authentifizierungsimplementierung in der Web-API verstanden wurde, ist es sehr einfach, andere Formen der Authentifizierung zu aktivieren. Nur der Authentifizierungsprozess unterscheidet sich, und die Web-API-Hooks, an denen dies ausgeführt wird, sind die gleichen.
Zur Überprüfung der Benutzeranmeldeinformationen erstellen wir eine IPrincipal
Objekt, das den aktuellen Sicherheitskontext darstellt.
Fügen Sie einen neuen Ordner mit dem Namen hinzu Sicherheit
und eine neue Klasse TestAPIPrincipal.cs
drin.
öffentliche Klasse TestAPIPrincipal: IPrincipal // Konstruktor public TestAPIPrincipal (Zeichenfolge Benutzername) Benutzername = Benutzername; Identität = neue GenericIdentity (Benutzername); öffentliche Zeichenfolge Benutzername get; einstellen; public IIdentity Identity get; einstellen; public bool IsInRole (Zeichenfolgenrolle) if (role.Equals ("user")) return true; else return false;
Das IIdentity
Objekt, das dem Principal zugeordnet ist, hat eine Eigenschaft, die aufgerufen wird IsAuthenticated
. Wenn der Benutzer authentifiziert ist, gibt diese Eigenschaft true zurück. Andernfalls wird falsch zurückgegeben.
Jetzt erstellen wir einen anderen Handler namens AuthHandler.cs
.
öffentliche Klasse AuthHandler: DelegatingHandler string _userName = ""; // Methode zum Überprüfen der Anmeldeinformationen aus der Autorisierung // Headerwert private bool ValidateCredentials (AuthenticationHeaderValue authenticationHeaderVal) try if (authenticationHeaderVal! = Null &&! String.IsNullOrEmpty (authenticationHeaderVal.Parameter)) Zeichenfolge [] decodedCredentials = Encoding.ASC.Ac (Convert.FromBase64String (authenticationHeaderVal.Parameter)) .Split (new [] ':'); // jetzt decodedCredentials [0] enthält // Benutzername und decodedCredentials [1] enthält // ein Kennwort. if (decodedCredentials [0] .Equals ("Benutzername") && decodedCredentials [1] .Equals ("Passwort")) _userName = "John Doe"; Rückgabe true; // Authentifizierung anfordern. return false; // Anforderung nicht authentifiziert. catch return false; protected überschreibt den asynchronen TaskSendAsync (Anforderung HttpRequestMessage, Annullierungstoken für Annullierungstoken) // Wenn die Berechtigungsnachweise validiert sind, // setzen Sie CurrentPrincipal und Current.User if (ValidateCredentials (request.Headers.Authorization)) Thread.CurrentPrincipal = new TestAPIPrincipal (_userName); HttpContext.Current.User = new TestAPIPrincipal (_userName); // Führen Sie base.SendAsync aus, um die Standardaktionen auszuführen. // Erfassen Sie anschließend das Antwortobjekt und // den WWW-Authenticate-Header, wenn die Anforderung // als nicht autorisiert markiert wurde. // Zulassen, dass die Anforderung in der Pipeline weiter verarbeitet wird var response = await base.SendAsync (request, cancelToken); if (response.StatusCode == HttpStatusCode.Unauthorized &&! response.Headers.Contains ("WwwAuthenticate")) response.Headers.Add ("WwwAuthenticate", "Basic"); Antwort zurückschicken;
Diese Klasse enthält eine private Methode ValidateCredentials
, Dabei wird nach dekodierten Benutzernamen und Kennwortwerten aus dem HTTP-Anforderungsheader und der SendAsync
Methode zum Abfangen der HTTP-Anfrage.
Wenn die Anmeldeinformationen des Clients gültig sind, dann die aktuellen IPrincipal
Objekt wird an den aktuellen Thread angehängt, d. Thread.CurrentPrincipal
. Wir setzen auch die HttpContext.Current.User
um den Sicherheitskontext konsistent zu machen. Dadurch können wir von überall in der Anwendung auf die Daten des aktuellen Benutzers zugreifen.
Sobald die Anfrage authentifiziert ist, base.SendAsync
wird aufgerufen, um die Anforderung an den inneren Handler zu senden. Wenn die Antwort einen nicht autorisierten HTTP-Header enthält, fügt der Code a ein WwwAuthenticate
Kopfzeile mit dem Wert Basic
den Kunden darüber zu informieren, dass unser Service eine Basisauthentifizierung erwartet.
Nun müssen wir diesen Handler im registrieren Global.Asax
Klasse wie wir es für unsere gemacht haben ApiKeyHandler
. Stellen Sie sicher, dass die AuthHandler
Der Handler befindet sich unterhalb der ersten Handler-Registrierung, um die richtige Reihenfolge sicherzustellen.
GlobalConfiguration.Configuration.MessageHandlers.Add (new APIKeyHandler ()); GlobalConfiguration.Configuration.MessageHandlers.Add (new AuthHandler ());
Aber bevor wir die grundlegende Authentifizierung in Aktion sehen können, müssen wir zunächst eine Autorisierung implementieren.
Bei der Autorisierung wird überprüft, ob der authentifizierte Benutzer eine bestimmte Aktion ausführen oder eine bestimmte Ressource verwenden kann. Dieser Vorgang in der Web-API findet später in der Pipeline statt
Authentifizierung und bevor die Controller-Aktionen ausgeführt werden.
ASP.NET MVC-Web-API stellt einen Autorisierungsfilter bereit AuthorizeAttribute
was die Anfrage überprüft IPrincipal
, prüft seine Identity.IsAuthenticated
Eigenschaft und gibt ein 401 nicht Autorisiert
HTTP-Status, wenn der Wert falsch ist und die angeforderte Aktionsmethode nicht ausgeführt wird. Dieser Filter kann auf verschiedenen Ebenen wie der Controller - Ebene oder der Action - Ebene angewendet werden [Genehmigen]
Syntax auf Controllern oder Aktionen.
[Authorize] public class ClassifiedsController: ApiController
Sobald dieses Attribut festgelegt ist, wird verhindert, dass unberechtigte Benutzer auf alle Aktionsmethoden im Controller zugreifen können.
Zunächst setzt unser grundlegender Authentifizierungs-Handler ein, um die Identität des aktuellen Benutzers festzulegen IPrincipal
Objekt. Dann, bevor diese Anforderung die Steuerung erreicht, AuthorizeAttribute
Überprüft den Zugriff auf die jeweilige Steuerung / Aktion für den aktuellen Benutzer.
Um dies in Aktion zu sehen, erstellen Sie zunächst eine HTTP-Anfrage ohne korrekte Anmeldeinformationen.
Der Zugriff wird vom verweigert AuthorizeAttribute
.
Erstellen Sie nun eine weitere Anforderung mit dem Autorisierungskopfschlüssel / Wert wie folgt:
Genehmigung: Basic dXNlcm5hbWU6cGFzc3dvcmQ =
Hier der Wert dXNlcm5hbWU6cGFzc3dvcmQ =
ist derBase64-kodierte Form von Benutzername Passwort
.
Diese Anfrage erhält erwartungsgemäß Zugriffsrechte für die Steuerung / Aktion.
Dies ist ein Beispiel für die Sicherung der öffentlichen Aktionen des gesamten Controllers.
Wir können auch einige Teile der Controller-Aktionen einschränken, indem Sie das setzen[Genehmigen]
Attribut stattdessen nur auf Aktionsebene. Dadurch können wir sowohl geschützte als auch ungeschützte Aktionen in derselben Steuerung durchführen.
// [Authorize] public class ClassifiedsController: ApiController öffentliche ListeGet (String-ID) return ClassifiedService.GetClassifieds (ID); [Authorize] öffentliche Liste Get () return ClassifiedService.GetClassifieds ("");
Eine andere Möglichkeit, sowohl geschützte als auch ungeschützte Aktionen innerhalb des Controllers durchzuführen, ist die Verwendung der [AllowAnonymous]
Attribut. Wenn wir das einstellen [Genehmigen]
Attribut in der Controller-Ebene und setzen Sie [AllowAnonymous]
Attribut für jede Aktion innerhalb des Controllers, überspringt diese Aktion das [Genehmigen]
Attribut.
Es ist auch möglich, bestimmte Rollen und Benutzer nach Zugriffsrechten zu filtern. Zum Beispiel können wir so etwas haben [Autorisieren (Rollen = "Admin")]
auf die Controller und Aktionen.
Schließlich können wir auch unsere eigenen benutzerdefinierten Berechtigungsattribute erstellen, je nach unseren Bedürfnissen. Eine Möglichkeit, dies zu erreichen, ist die Erweiterung AuthorizeAttribute
.
Nehmen wir an, wir möchten unseren Web-API-Dienst auf nur bestimmte Teile der Welt beschränken, indem wir den Zugriff auf Benutzer beschränken, die sich nicht in einem bestimmten IP-Adressbereich befinden. Wir können für diesen Zweck ein benutzerdefiniertes Berechtigungsattribut erstellen, indem wir von dem abgeleitet werden AuthorizeAttribute
Klasse und das Überschreiben Ist berechtigt
Methode.
Öffentliche Klasse RestrictIPsAttribute: System.Web.Http.AuthorizeAttribute protected überschreibt Bool IsAuthorized (Kontext HttpActionContext) var ip = HttpContext.Current.Request.UserHostAddress; // hier nach ip suchen if (ip.Contains ("")) return true; falsch zurückgeben;
Sobald wir unser benutzerdefiniertes Berechtigungsattribut haben, können wir unsere Controller / Aktionen damit dekorieren.
[RestrictIPsAttribute] öffentliche ListeGet () return ClassifiedService.GetClassifieds ("");
In diesem Artikel haben wir untersucht, wie wir unseren ASP.NET-Web-API-Dienst sichern können, bevor der Dienst der Außenwelt zugänglich gemacht wird. Wir haben untersucht, wie wir HTTP-Anforderungen für gültige API-Schlüssel und für gültige Benutzeranmeldeinformationen authentifizieren können. Mit diesem großen Wissen bin ich der Meinung, dass wir bereit sind, jede individuelle Sicherheit für unsere APIs zu entwickeln.
Für diejenigen unter Ihnen, die entweder gerade mit Laravel beginnen oder Ihr Wissen, Ihre Site oder Anwendung mit Erweiterungen erweitern möchten, haben wir eine Vielzahl von Möglichkeiten, die Sie in Envato Market lernen können.
Ich hoffe, es hat Ihnen Spaß gemacht, so viel zu lesen, wie Sie aus diesem Artikel gelernt haben, und vergessen Sie nicht, Fragen oder Kommentare im Feed unten zu hinterlassen!