2010-01-13 12 views
7

Ich habe die rollenbasierte Autorisierung in ASP.NET erfolgreich implementiert. Wenn eine Person nicht die erforderliche Rolle hat, wird eine Fehlerseite für 401.2 angezeigt, die nicht autorisiert ist.customerrors für 401.2 in ASP.NET

Was ich jetzt erreichen möchte, ist eine benutzerdefinierte 401-Seite in meiner Anwendung zu haben und sie dort über Einstellungen in der web.config weitergeleitet werden. Ich habe es versucht:

<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm"> 
    <error statusCode="401" redirect="NoAccess.htm" /> 
</customErrors> 

Aber das wird nicht erwischt. Muss ich es stattdessen in IIS überschreiben? Ich hoffe nicht, dass dies die Bereitstellung von Dingen erschweren würde.

Antwort

7

Ich lief vor kurzem das gleiche Problem und es stellt sich heraus, dass dies eine der Macken bei der Verwendung der Windows-Authentifizierung ist.

Joshua Flanagan hat vor einiger Zeit eine nice HttpModule erstellt, die den customErrors-Abschnitt in Ihrer web.config berücksichtigt und auf die 401-Fehlerseite umleitet.

Der Schlüssel zur Lösung ist, die Endrequest Ereignis der Seite Lebenszyklus, überprüfen Sie für einen Statuscode 401 abzufangen und anschließend die benutzerdefinierte Seite auszuführen.

Die Portabilität der Httpmodule ist schön, weil es die Lösung wiederverwendbar macht und hält Ihren Global.asax sauber, aber es gibt nichts mehr im Weg steht Wiring der Endrequest-Ereignisses in dem Global.asax mit seinem Code, wenn Sie wirklich nach oben wollte.

Wenn Sie ASP.NET MVC verwenden, ist die Lösung nicht ganz so elegant.

3

Wenn Sie nicht möchten, dass ein Httpmodule

in web.config

<system.web> 
    <customErrors mode="On" defaultRedirect="~/MyController/MyErrorAction/" redirectMode="ResponseRedirect"> 
     <error statusCode="401" redirect="~/MyController/MyErrorAction/" /> 
    </customErrors> 

in global.asax.cs

protected void Application_EndRequest(object sender, EventArgs e) 
    { 
     HttpApplication application = (HttpApplication)sender; 

     if (application.Response.StatusCode != 401 || !application.Request.IsAuthenticated) return; 

     application.Response.ClearContent(); 

     //You can replace the piece below is to redirect using MVC, or your can replace all this with application.Server.Execute(yourPage); 
     IController errorController = new SharedController(); 
     var rd = new RouteData(); 
     rd.Values.Add("controller", "MyController"); 
     rd.Values.Add("action", "MyErrorAction"); 
     rd.Values.Add("value", "You or your user group do not have permissions to use the address: " + Request.Url.PathAndQuery); 

     errorController.Execute(new RequestContext(new HttpContextWrapper(Context), rd)); 
     HttpContext.Current.Server.ClearError(); 
    } 
+0

Ist die Negation des IsAuthenticated wirklich richtig? Sollte es nicht umgekehrt sein, d.h. wenn authentifiziert => Rückkehr von der Methode? – aeliusd

3

Hier ist ein MVC Agnostiker Variante hinzuzufügen:

In Web.config

<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm"> 
    <error statusCode="401" redirect="NoAccess.htm" /> 
</customErrors> 

In Global.asax.cs

protected void Application_EndRequest(object sender, EventArgs e) 
{ 
    HttpApplication application = (HttpApplication)sender; 

    if (application.Response.StatusCode != 401 || !application.Request.IsAuthenticated) return; 

    var customErrors = (CustomErrorsSection)ConfigurationManager.GetSection("system.web/customErrors"); 

    var accessDeniedPath = customErrors.Errors["401"] != null ? customErrors.Errors["401"].Redirect : customErrors.DefaultRedirect; 
    if (string.IsNullOrEmpty(accessDeniedPath)) 
     return; // Let other code handle it (probably IIS). 

    application.Response.ClearContent(); 
    application.Server.Execute(accessDeniedPath); 
    HttpContext.Current.Server.ClearError(); 
} 
2

Hier ist, was für mich gut funktioniert.

Global.asax -

protected void Application_EndRequest(object sender, EventArgs e) 
    { 
     if (Response.StatusCode == 401 && Request.IsAuthenticated) 
     { 
      Response.StatusCode = 303; 
      Response.Clear(); 
      Response.Redirect("~/AccessDenied.html"); 
      Response.End(); 
     } 
    } 

Web.config -

<system.web> 
    <customErrors mode="On"> 
     <error statusCode="401" redirect="AccessDenied.html"/> 
    </customErrors> 
    <authentication mode="Windows"/> 
    </system.web> 
    <location path="AccessDenied.html"> 
    <system.web> 
     <authorization> 
     <allow roles="*"/> 
     </authorization> 
    </system.web> 
    </location> 
    <location path="."> 
    <system.web> 
     <authorization> 
     <allow roles="YourADGroup"/> 
     <deny users="*" /> 
     </authorization> 
    </system.web> 
    </location> 

Diese kümmert sich um die Doppel 401 vor einem 200-Ausgabe als auch. Umgeht auch das lästige firefox Authentifizierungs-Popup.