2010-01-13 2 views
7

J'ai implémenté avec succès l'autorisation basée sur les rôles dans ASP.NET. Quand une personne n'a pas le rôle nécessaire, elle peut voir une page d'erreur pour 401.2 non autorisée.customerrors pour 401.2 dans ASP.NET

Ce que je voudrais accomplir maintenant est d'avoir une page 401 personnalisée dans mon application et l'avoir redirigée via les paramètres du web.config. J'ai essayé ceci:

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

Mais cela ne se coince pas. Dois-je le remplacer dans IIS à la place? J'espère que non, car cela rendrait les choses plus difficiles à déployer.

Répondre

7

J'ai récemment rencontré le même problème et il s'avère que c'est l'une des bizarreries lors de l'utilisation de l'authentification Windows.

Joshua Flanagan a créé un nice HttpModule il y a quelque temps qui respectera la section customErrors dans votre web.config et redirigera vers la page d'erreur 401.

La clé de la solution est d'intercepter le EndRequest événement du cycle de vie de la page, vérifier un code d'état 401, puis exécutez votre page personnalisée.

La portabilité du HttpModule est agréable car il rend la solution réutilisable, et maintient votre Global.asax propre, mais il n'y a rien qui vous empêche de câblage votre événement EndRequest dans le Global.asax avec son code si vous avez vraiment voulait.

Si vous utilisez ASP.NET MVC, la solution n'est pas aussi élégante.

3

Si vous ne voulez pas ajouter un HttpModule

dans web.config

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

dans 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 négation de l'IsAuthenticated est-elle vraiment correcte? Ne devrait-il pas être l'inverse, c'est-à-dire si authentifié => retour de la méthode? – aeliusd

3

Voici une variante agnostique MVC:

Dans Web.config

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

Dans 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

Voilà ce qui a bien fonctionné pour moi.

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> 

Cela prend en charge la double 401 avant une question 200 ainsi. contourne également la popup popup d'authentification de Firefox.

Questions connexes