wake-up-neo.com

Wie richte ich eine nicht autorisierte Seite ein, wenn sich ein Benutzer nicht in den autorisierten Rollen befindet?

Ich verwende das Attribut Authorize wie folgt:

[Authorize (Roles="Admin, User")]
Public ActionResult Index(int id)
{
    // blah
}

Wenn sich ein Benutzer nicht in den angegebenen Rollen befindet, wird eine Fehlerseite angezeigt (Ressource nicht gefunden). Also habe ich auch das Attribut HandleError eingefügt.

[Authorize (Roles="Admin, User"), HandleError]
Public ActionResult Index(int id)
{
    // blah
}

Jetzt geht es zur Login Seite, wenn der Benutzer nicht in den angegebenen Rollen ist.

Wie kann ich eine nicht autorisierte Seite anstelle der Anmeldeseite aufrufen, wenn ein Benutzer eine der erforderlichen Rollen nicht erfüllt? Und wenn ein anderer Fehler auftritt, wie unterscheide ich diesen Fehler von einem nicht autorisierten Fehler und behandle ihn anders?

39
Robert Harvey

Fügen Sie Ihrer web.config so etwas hinzu:

<customErrors mode="On" defaultRedirect="~/Login">
     <error statusCode="401" redirect="~/Unauthorized" />
     <error statusCode="404" redirect="~/PageNotFound" />
</customErrors>

Sie sollten natürlich die Routen, Aktionen und Ansichten von /PageNotFound und /Unauthorized erstellen.

EDIT: Es tut mir leid, ich habe das Problem offenbar nicht richtig verstanden. 

Das Problem ist, dass bei der Ausführung des AuthorizeAttribute-Filters entschieden wird, dass der Benutzer die Anforderungen nicht erfüllt (er/sie ist möglicherweise angemeldet, hat aber keine korrekte Rolle). Daher wird der Antwortstatuscode auf 401 gesetzt. Dieser wird vom Modul FormsAuthentication abgefangen, das dann die Umleitung ausführt.

Ich sehe zwei Alternativen: 

  1. Deaktivieren Sie den defaultRedirect.

  2. Erstellen Sie Ihre eigene IAuthorizationFilter. Leiten Sie von AuthorizeAttribute ab und überschreiben Sie HandleUnauthorizedRequest. Wenn der Benutzer authentifiziert ist, führen Sie in dieser Methode eine redirect to/Unauthorized durch

Das gefällt mir auch nicht: Die defaultRedirect-Funktion ist Nice und nicht etwas, das Sie selbst implementieren möchten. Der zweite Ansatz führt dazu, dass dem Benutzer eine visuell korrekte Seite "Sie sind nicht autorisiert" bedient werden, die HTTP-Statuscodes sind jedoch nicht die gewünschten 401.

Ich weiß nicht genug über HttpModules, um zu sagen, ob dies mit einem erträglichen Hack umgangen werden kann.

EDIT 2 : Wie wäre es, Ihren eigenen IAuthorizationFilter auf folgende Weise zu implementieren: Laden Sie den MVC2-Code von CodePlex herunter und "leihen" Sie den Code für AuthorizeAttribute. Ändern Sie die OnAuthorization-Methode so, wie sie aussieht

    public virtual void OnAuthorization(AuthorizationContext filterContext)
    {
        if (AuthorizeCore(filterContext.HttpContext))
        { 
            HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
            cachePolicy.SetProxyMaxAge(new TimeSpan(0));
            cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
        }
        // Is user logged in?
        else if(filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            // Redirect to custom Unauthorized page
            filterContext.Result = new RedirectResult(unauthorizedUrl);
        } 
        else {
            // Handle in the usual way
            HandleUnauthorizedRequest(filterContext);
        }
    }

dabei ist unauthorizedUrl entweder eine Eigenschaft im Filter oder wird aus Web.config gelesen.

Sie könnten auch von AuthorizeAttribute erben und OnAuthorization überschreiben, würden aber am Ende ein paar private Methoden schreiben, die bereits in AuthorizeAttribute enthalten sind.

27
Rune

Sie können dies auf zwei Arten tun:

  1. Geben Sie den Fehler des HandleError-Attributs an und geben Sie eine Ansicht an, die angezeigt werden soll:

    [HandleError (ExceptionType = typeof (UnAuthorizedException), View = "UnauthorizedError")]]

Sie können mehrere verschiedene ExceptionTypes und -Ansichten angeben

  1. Erstellen Sie einen benutzerdefinierten ActionFilter, prüfen Sie die Anmeldeinformationen und leiten Sie ihn an einen Controller weiter, wenn der Benutzer nicht autorisiert ist .: http://web.archive.org/web/20090322055514/http://msdn.Microsoft.com/de -us/library/dd381609.aspx
7
Pbirkoff

Möglicherweise ist ein Statuscode 403 aufgrund Ihrer Frage besser geeignet (der Benutzer wird identifiziert, sein Konto ist jedoch nicht privilegiert). 401 ist für den Fall, dass Sie nicht wissen, welche Privilegien der Benutzer hat.

4
628426

Und HttpUnauthorizedResult (dies ist eine Neuverwendung der AuthorizeAtrribute) setzt StatusCode einfach auf 401. Wahrscheinlich können Sie die Seite 401 in IIS oder benutzerdefinierte Fehlerseiten in web.config einrichten. Natürlich müssen Sie auch sicherstellen, dass der Zugriff auf Ihre benutzerdefinierte Fehlerseite nicht autorisiert werden muss.

3
Mike Chaliy

Überschreiben Sie einfach die HandleUnauthorizedRequest-Methode von AuthorizeAttribute. Wenn diese Methode aufgerufen wird, der Benutzer jedoch IS authentifiziert ist, können Sie auf Ihre "nicht autorisierte" Seite umleiten.

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { Area = "", Controller = "Error", Action = "Unauthorized" }));
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}
0
Davy