2010-01-13 19 views
7

Ho implementato con successo l'autorizzazione basata sui ruoli in ASP.NET. Quando una persona non ha il ruolo necessario, può vedere una pagina di errore per 401.2 non autorizzata.customerrors per 401.2 in ASP.NET

Quello che mi piacerebbe realizzare ora è avere una pagina 401 personalizzata nella mia applicazione e averla reindirizzata lì tramite le impostazioni nel web.config. Ho provato questo:

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

Ma questo non viene catturato. Devo sovrascriverlo in IIS? Spero di no perché ciò renderebbe le cose più difficili da implementare.

risposta

7

Mi sono imbattuto nello stesso problema di recente e si scopre che questo è uno dei quirks quando si utilizza l'autenticazione di Windows.

Joshua Flanagan ha creato un tempo fa nice HttpModule che rispetterà la sezione customErrors nel proprio web.config e reindirizzerà alla pagina di errore 401.

La chiave per la soluzione è quella di intercettare l'evento EndRequest della pagina del ciclo di vita, verificare la presenza di un codice di stato 401, e quindi eseguire la vostra pagina personalizzata.

La portabilità del HttpModule è bello perché rende la soluzione riutilizzabile, e mantiene il vostro Global.asax pulita, ma non c'è nulla ti impedisce di cablaggio il vostro EndRequest evento nel Global.asax con il suo codice, se davvero voleva.

Se si utilizza ASP.NET MVC, la soluzione non è altrettanto elegante.

3

Se non si desidera aggiungere un 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

La negazione di IsAuthenticated è corretta? Non dovrebbe essere il contrario, cioè se authenticated => return from method? – aeliusd

3

Ecco una variante agnostica MVC:

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

Ecco che cosa ha funzionato bene per me.

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> 

Questo si prende cura del doppio 401 prima di un problema di 200 pure. aggira anche il fastidioso popup di autenticazione di firefox.

Problemi correlati