2013-03-31 5 views
7

Ich bin mit ASP.NET Web API. Und ich mag die Fähigkeit, Attribute hinzufügen Ebenen der Zugriff auf die API-Controller wie folgt zu spezifizieren:Wie ASP.NET Web API 403 oder 401 entsprechend reagieren lassen?

[Authorize] 
public IEnumerable<Activity> Get() 

So weit so gut, aber wenn ich Rollen verwenden das Konzept bricht auseinander.

[Authorize(Roles = "Manager")] 
public IEnumerable<Activity> Get() 

Mein Benutzer eine Weile an dem System angemeldet zurück haben kann und dann irgendwann schlugen sie eine Ressource, die „verboten“ zu ihnen. Es hat keinen Sinn, wenn der Benutzer versucht, sich erneut anzumelden. Da ihr rechtmäßiger Account keinen Zugriff auf diese URL hat. Aber im Moment bekommen sie 401 (nicht autorisiert) anstelle von 403 (verboten), als hätten sie sich mit dem falschen Account eingeloggt. Der Benutzer hat jedoch nur einen Account und es ist nicht beabsichtigt, dass Nutzer nach einem Account fragen, der jemand anderem gehört.

Hat jemand mit diesem Problem umgegangen? Kann jemand das beheben? Ich bin mehr als willens, den Code zu schreiben, um das zu beheben, aber ich weiß momentan nicht, wo ich anfangen soll.

Antwort

0

, was Sie tun können, ist eine benutzerdefinierte machen Authorize attribute und dann behandeln die AuthorizeCore und OnAuthorizationFailed im letzteren kann man Sie, was Antwort Sie ein look here

+0

Ändern der AuthorizeAttribue war die Antwort. In diesem speziellen Beispiel wird System.Web.Mvc anstelle von System.Web.Http geändert, da ich die WebAPI verwende. –

+0

Ich dachte, Sie möchten ein benutzerdefiniertes Attribut erstellen, um die HTTP-Statuscodes zurückzusenden, die Ihnen gefallen –

+0

Und das ist, was ich getan habe, ich geerbt von System.Web.Http.AuthorizeAtribute. Nicht von System.Web.Mvc.AuthorizeAtribute, auf das sich der Artikel bezieht, auf den Sie verwiesen haben. –

1

Ich habe ein wenig Forschung senden preffer

haben und Ich habe eine Lösung für mich programmiert. Ich habe zwei verschiedene Autorize-Attribute in System.Web.Mvc und eine zweite in System.Web.Http gefunden. Die erste gilt für eine regelmäßige MVC4 app und die zweite an den WebAPI Teil MVC4 für Web-Services einschließlich RESTful Schnittstellen verwendet. Also habe ich den zweiten benutzt.

Ich habe daran gedacht, den Authorize Attribute Source Code auf Codeplex zu suchen. Und ich fand dies:

protected virtual bool IsAuthorized(HttpActionContext actionContext) 
    { 
     if (actionContext == null) 
     { 
      throw Error.ArgumentNull("actionContext"); 
     } 

     IPrincipal user = Thread.CurrentPrincipal; 
     if (user == null || !user.Identity.IsAuthenticated) 
     { 
      return false; 
     } 

     if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase)) 
     { 
      return false; 
     } 

     if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole)) 
     { 
      return false; 
     } 

     return true; 
    } 

Es ist leicht zu sehen, wie die Authentifizierung und Zugang werden durch die Tatsache verschmelzt, dass sie beide haben die gleiche Wirkung von falschen zurück. Hier

ist ein new AuthorizeAttribute schrieb ich, dass 403 zurückgibt, wenn der Benutzer oder Rollen nicht übereinstimmen. Auf diese Weise vermeiden Sie, ein natives Anmeldefenster zu erhalten. Es enthält den folgenden Code.

 if (!IsAuthorized(actionContext)) 
     { 
      HandleUnauthorizedRequest(actionContext); 
     } 

     if (!IsAllowed(actionContext)) 
     { 
      HandleForbiddenRequest(actionContext); 
     } 
23

Lese Parv Vorschlag, habe ich die folgenden benutzerdefinierten Filter genannt [WebApiAuthorize].

Der Schlüssel ist die HandleUnauthorizedRequest() Methode. Wenn Code innerhalb dieser Methode ausgeführt wird, ist es, weil der Benutzer „aus irgendeinem Grund“ nicht autorisiert ist .... so jetzt nur bestimmen heraus, dass wir „warum“ .... und dann entweder:

  1. Anrufbasismethode für Standardverhalten (401 zurück) .... oder ....
  2. Rück unsere eigene Antwort mit einem 403.

Wie Sie sehen können, gibt es 403 bei Bedarf (authentifiziert, aber nicht autorisiert) .

public class WebApiAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(HttpActionContext ctx) 
    { 
     if (!ctx.RequestContext.Principal.Identity.IsAuthenticated) 
      base.HandleUnauthorizedRequest(ctx); 
     else 
     { 
      // Authenticated, but not AUTHORIZED. Return 403 instead! 
      ctx.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden); 
     } 
    } 
} 

zu bedienen, einfach die Filter auf einem wie diesen Controller oder benutzerdefinierte Aktion werfen .....

[WebApiAuthorize(Roles = "YourRoleA,YourRoleB")] 
public class AdminController : ApiController 
{ 
    public List<Admin> GetAdmins() 
    { 
     ... 
    } 
} 
+0

kleine Verbesserung fehlschlägt. Sie sollten prüfen, ob Principal oder Identity null ist, andernfalls könnten Sie eine NullReferenceException erhalten, wenn auf Anforderung keine Anmeldeinformationen bereitgestellt werden. ".protected bool IsAuthenticated (HttpActionContext ctx) { var principal = ctx.RequestContext.Principal; Rückgabe principal! = Null && principal.Identity! = Null && principal.Identity.IsAuthenticated; } ' – Jehof