2010-01-13 13 views
7

Implementé correctamente la autorización basada en roles en ASP.NET. Cuando una persona no tiene la función necesaria, puede ver una página de error para 401.2 no autorizada.customerrors for 401.2 in ASP.NET

Lo que me gustaría lograr ahora es tener una página 401 personalizada en mi aplicación y hacerla redirigir a través de la configuración en el web.config. Intenté esto:

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

Pero esto no se atrapa. ¿Debo reemplazarlo en IIS? Espero que no, ya que eso haría que implementar las cosas sea más difícil.

Respuesta

7

Me encontré con el mismo problema recientemente y resulta que esta es una de las peculiaridades cuando se usa la Autenticación de Windows.

Hace un tiempo, Joshua Flanagan creó un nice HttpModule que respetará la sección customErrors en su web.config y lo redireccionará a la página de error 401.

La clave para la solución es interceptar el evento EndRequest de la página del ciclo de vida, compruebe si hay un código de estado 401, y luego ejecutar su página personalizada.

La portabilidad del HttpModule es bueno porque hace que la solución reutilizable, y mantiene su Global.asax limpio, pero no hay nada que nos impida el cableado de su evento EndRequest en el Global.asax con su código si realmente quería.

Si está utilizando ASP.NET MVC, la solución no es tan elegante.

3

Si no desea añadir un HttpModule

en web.config

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

en 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

¿Es realmente correcta la negación de IsAuthenticated? ¿No debería ser al revés, es decir, si está autenticado => regresar del método? – aeliusd

3

Aquí está una variante agnóstico MVC:

En Web.config

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

En 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

Esto es lo que ha funcionado bien para mí.

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> 

Este se encarga de la doble 401 antes de que un tema 200 también. También elude la ventana emergente de autenticación molesta de Firefox.

Cuestiones relacionadas