29

Ich implementiere einen RESTful-Webdienst mit ASP.Net Web API. Ich habe beschlossen, die Standardauthentifizierung + SSL für den Authentifizierungsteil zu verwenden. Was ist der beste/korrekte Weg dies zu implementieren?ASP.NET-Web-API RESTful Web-Service + Standardauthentifizierung

Mein erster Versuch war, es manuell zu tun, den Authorization-Header analysierend, den Benutzer gegen meine Datenbank entschlüsselnd und verifizierend. Es funktioniert, aber ich frage mich, ob ich etwas vermisse.

Ich habe einige Lösungen mit Benutzerrollen und Prinzipalen gesehen. Obwohl ich nicht sicher bin, was diese tatsächlich tun, bin ich mir fast sicher, dass ich diese nicht brauche, da ich in meiner Datenbank meine eigenen Benutzer und ihre Rollen definiere.

Auch was ich noch nicht vollständig verstehe, ist, wenn die Verbraucher des Dienstes die Anmeldeinformationen bei jeder Anfrage gesendet haben müssen oder sie irgendwie zwischengespeichert werden. Sollte mein Dienst etwas tun, damit dies geschieht, oder liegt es in der Verantwortung des Verbrauchers, damit umzugehen?

Und eine letzte Frage über Kunden Anfragen mit Javascript. Gäbe es Probleme mit der "domainübergreifenden Anfrage", wenn sie versuchen, den Service zu nutzen?

Antwort

25

Jamie Kurtze bietet eine gute Erklärung der Verwendung von Standardauthentifizierung hier ASP.NET Web API REST Security Basics

Wenn Sie möchten, dass Ihre Anforderungen statusfrei sind, müssen Sie jede Anfrage anfordern e Das zu setzende Authentifizierungsfeld

Jamie Kurtze umschließt den erforderlichen Code in einer von DelegateHandler abgeleiteten Klasse, während Rick Strahl prüft, ob der Aufruf mit einem Filter gültig ist. Weitere Informationen finden Sie in seinem Blogbeitrag unter A WebAPI Basic Authentication Authorization Filter

+0

Hallo, als ich die Frage schrieb, war mir nicht klar, wie die Prinzipale und Rollen verwendet werden (und wie sie mit meinen eigenen Benutzern zusammenhängen). Was ich jetzt mache, benutzt den Authentication-Header, um die Credentials zu übergeben und ein Http-Modul, um sie einheitlich zu prüfen. Ich werde jedoch einen Blick auf Ihre Links werfen, wenn ich etwas Zeit habe. – alfoks

+0

Meine Implementierung funktioniert jetzt gut, aber das sind gute Links für zukünftige Leser. – alfoks

+1

Ihr erster Link die ASP.NET Web Api REST Sicherheitsgrundlagen ist tot –

1
+0

Diese Links beantworten meine Fragen nicht wirklich. Nur die erste Frage vielleicht, aber sie beziehen sich auf die Konfiguration einer Drittanbieter-Sicherheitsbibliothek. Wegen der fehlenden Zeit möchte ich vermeiden, mehr Bibliotheken zu verwenden. – alfoks

21

Verwenden Sie die Standardauthentifizierung für die erste Anforderung (Anmelden), indem Sie den entsprechenden Controllern/Methoden ein [BasicHttpAuthorize]-Attribut hinzufügen. Geben Sie bei Bedarf das Attribut Users und Roles mit dem Attribut an. Definieren BasicHttpAuthorizeAttribute als spezialisierter AuthorizeAttribute wie folgt aus:

public class BasicHttpAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected override bool IsAuthorized(HttpActionContext actionContext) 
    { 
     if (Thread.CurrentPrincipal.Identity.Name.Length == 0) { // If an identity has not already been established by other means: 
      AuthenticationHeaderValue auth = actionContext.Request.Headers.Authorization; 
      if (string.Compare(auth.Scheme, "Basic", StringComparison.OrdinalIgnoreCase) == 0) { 
       string credentials = UTF8Encoding.UTF8.GetString(Convert.FromBase64String(auth.Parameter)); 
       int separatorIndex = credentials.IndexOf(':'); 
       if (separatorIndex >= 0) { 
        string userName = credentials.Substring(0, separatorIndex); 
        string password = credentials.Substring(separatorIndex + 1); 
        if (Membership.ValidateUser(userName, password)) 
         Thread.CurrentPrincipal = actionContext.ControllerContext.RequestContext.Principal = new GenericPrincipal(new GenericIdentity(userName, "Basic"), System.Web.Security.Roles.Provider.GetRolesForUser(userName)); 
       } 
      } 
     } 
     return base.IsAuthorized(actionContext); 
    } 
} 

Haben die erste Reaktion umfassen einen API-Schlüssel für den Benutzer. Verwenden Sie den API-Schlüssel für nachfolgende Aufrufe. Auf diese Weise bleibt die Authentifizierung des Clients auch dann gültig, wenn der Benutzer den Benutzernamen oder das Passwort ändert. Wenn Sie jedoch das Kennwort ändern, geben Sie dem Benutzer eine Option zum Trennen von Clients, die Sie implementieren, indem Sie den API-Schlüssel auf dem Server löschen.

+0

Ich habe das Problem bereits gelöst aber danke für die Antwort. Ich finde es einfacher, in allen API-Aufrufen den Benutzernamen und das Kennwort im Berechtigungsheader zu übergeben, anstatt den von Ihnen vorgeschlagenen Token-Ansatz zu verwenden. – alfoks

+0

@Edward Vielen Dank für Ihren Beitrag, ich finde es am meisten helfen voll. Welchen Benutzer- und Rollenmechanismus verwenden Sie in diesem Beispiel? Weil ich sehe, dass Sie ein neues GenericPrinsiple erstellen. Könnten Sie mir bitte näher erläutern, wie ich Ihre Lösung in ein neues leeres Web-API-Projekt integrieren kann? – Zapnologica

+0

@Zapnologica Dieser Code verwendet das alte Mitgliedschaftsidentitätsmodell, das Microsoft vor VS2013 verwendet hat. Die Vorlagen mit VS2013 verwenden das neue OWIN-basierte Identitätssystem, das eine benutzerdefinierte Benutzername/Passwort-Authentifizierung gefolgt von der Verwendung von Trägertokens durchführt, wodurch die Notwendigkeit von BasicHttpAuthorize entfällt. –