2016-08-05 44 views
2

Ich versuche, einen benutzerdefinierten Filter für meine Web-API-Controller Teil einer ASP.NET MVC 5 Website/Anwendung, um die Anforderungen Header für ein bestimmtes Token zu überprüfen, die ich in der Datenbank gespeichert habe. Die meisten Beispiele, die ich gefunden habe, enthielten Benutzeranmeldeinformationen und anschließend wurde der Benutzer mithilfe der Identität authentifiziert. Nicht genau wonach ich suche.Web API benutzerdefinierten Authentifizierungsfilter

Dies ist die tutorial die ich gefunden habe und derzeit befolge.

Die Web-API sollte nur "externe" HTTP-Aufrufe verarbeiten, die Website-Seite wird derzeit eigene Controller haben (kann aber Änderungen unterliegen).

Dieser Filter sollte, wenn möglich, mit dem bereits vorhandenen Identität 2-System verbunden sein.

Was ich tue ist, dass ich Benutzeranmeldeinformationen sende, dann ein Token dem Benutzer zuweisen und dann möchte ich dieses Token verwenden, um die Anfrage zu authentifizieren. Gibt es eine Möglichkeit, die Anfrage nur anhand des Tokens zu filtern oder muss ich Owin-Identität und ihre Token-Verwaltung verwenden? Ich benutze einen mobilen Client (derzeit iOS, wird auch Android enthalten), um die Anrufe zu tätigen. Irgendein Beispiel oder Tutorial, auf das ich mich beziehen könnte?

Das Token ist derzeit eine zufällige Kombination aus alphanumerischen Zeichen und Symbolen.

Vielen Dank.

P.S. Ich kann Code-Snippets und andere Dinge schreiben, wo sie benötigt werden.

Bearbeiten: Die HTTPRequests werden gefiltert, je nachdem, ob sie ein Token in unserer Datenbank/System enthalten. Anfragen, die ein Token enthalten oder in unserem System nicht vorhanden sind, erhalten einen unautorisierten Fehler (401?)

+0

Also ist das Token in der HTTP-Anfrage-Header? – Botonomous

+0

Ja, das Token befindet sich im Anforderungsheader. – beowulf

+0

Was meinst du damit, die Anfrage basierend auf dem Token zu filtern? Wird nicht jedes HTTPReq-Feld das Token enthalten oder müssen nur Anforderungen gefiltert werden, wenn sie ein Token haben? – Botonomous

Antwort

5

Angenommen, Sie denken, dass das Senden des Benutzernamens und des Kennworts an jede Anfrage nicht gut ist. Verweisen Sie meine folgende Implementierung ohne Benutzernamen und Passwort, da wir bei jeder Anfrage keinen Benutzernamen und kein Passwort senden.

public class AuthenticationFilter : AuthorizationFilterAttribute 
    { 
     /// <summary> 
     /// read requested header and validated 
     /// </summary> 
     /// <param name="actionContext"></param> 
     public override void OnAuthorization(HttpActionContext actionContext) 
     { 
      var identity = FetchFromHeader(actionContext); 

      if(identity != null) 
      { 
       var securityService = actionContext.ControllerContext.Configuration.DependencyResolver.GetService(typeof(ILoginService)) as ILoginService; 
       if (securityService.TokenAuthentication(identity)) 
       { 
        CurrentThread.SetPrincipal(new GenericPrincipal(new GenericIdentity(identity), null), null, null); 
       } 
       else 
       { 
        actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized); 
        return; 
       } 
      } 
      else 
      { 
       actionContext.Response = new HttpResponseMessage(HttpStatusCode.BadRequest); 
       return; 
      } 
      base.OnAuthorization(actionContext); 
     } 

     /// <summary> 
     /// retrive header detail from the request 
     /// </summary> 
     /// <param name="actionContext"></param> 
     /// <returns></returns> 
     private string FetchFromHeader(HttpActionContext actionContext) 
     { 
      string requestToken = null; 

      var authRequest = actionContext.Request.Headers.Authorization; 
      if (authRequest != null && !string.IsNullOrEmpty(authRequest.Scheme) && authRequest.Scheme == "Basic") 
       requestToken = authRequest.Parameter; 

      return requestToken; 
     } 
    } 
2

Sie können diese Filtereinheit testbar machen, indem Sie die Dienstabhängigkeiten über die Eigenschaft injizieren (Property Injection). Bei benutzerdefinierten Attributen möchten wir die Abhängigkeiten nicht über Konstruktor übergeben. Wir wollen das Attribut einfach auf setzen. Neu zu schreiben, was @Raj bereits begonnen, es kann wie folgt aussehen:

public class AuthenticationFilter : AuthorizationFilterAttribute 
    { 
     [Dependency] 
     public ILoginService LoginService { get; set; } 

     /// <summary> 
     /// read requested header and validated 
     /// </summary> 
     /// <param name="actionContext"></param> 
     public override void OnAuthorization(HttpActionContext actionContext) 
     { 
      var identity = FetchFromHeader(actionContext); 

      if (identity != null) 
      { 
       if (LoginService.TokenAuthentication(identity)) 
       { 
        CurrentThread.SetPrincipal(new GenericPrincipal(new GenericIdentity(identity), null), null, null); 

        //IPrincipal principal = new GenericPrincipal(new GenericIdentity(identity), new string[] { "myRole" }); 
        //Thread.CurrentPrincipal = principal; 
        //HttpContext.Current.User = principal;    
       } 
       else 
       { 
        actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized); 
        return; 
       } 
      } 
      else 
      { 
       actionContext.Response = new HttpResponseMessage(HttpStatusCode.BadRequest); 
       return; 
      } 
      base.OnAuthorization(actionContext); 
     } 

     /// <summary> 
     /// retrive header detail from the request 
     /// </summary> 
     /// <param name="actionContext"></param> 
     /// <returns></returns> 
     private string FetchFromHeader(HttpActionContext actionContext) 
     { 
      string requestToken = null; 

      var authRequest = actionContext.Request.Headers.Authorization; 
      if (authRequest != null && !string.IsNullOrEmpty(authRequest.Scheme) && authRequest.Scheme == "Basic") 
       requestToken = authRequest.Parameter; 

      return requestToken; 
     } 
    } 
-1

Vielen Dank für Antworten, nach einigen Experimenten mir die ganze API überarbeitet OAuth 2-Authentifizierung mit Inhaber Token zu verwenden. Es löste mein Problem mit den Filtern.