2010-08-02 19 views
6

Così, ho applicazioni web con web.configs in questo modo:Determina se la pagina corrente richiede l'autorizzazione?

<authorization> 
    <deny users="?"/> 
</authorization> 
... 
<location path="SomeUnsecuredPage.aspx"> 
    <system.web> 
    <authorization> 
     <allow users="*"/> 
    </authorization> 
    </system.web> 
</location> 

In altre parole, la maggior parte delle pagine richiedono l'autenticazione e l'autorizzazione, ma alcuni non lo fanno.

Quindi ho un IHttpModule che verrà utilizzato da tutte le diverse applicazioni. Tutto quello che voglio fare è controllare se la richiesta corrente è "protetta". Se la pagina non richiede l'autorizzazione, non voglio che il mio IHttpModule faccia qualcosa. Sto usando FormsAuthentication e presumo che FormsAuthentication abbia già tutte queste informazioni in cache da qualche parte, vero? Inoltre, poiché questo controllo verrà eseguito costantemente, deve essere molto veloce.

Attualmente sottoscrivo la HttpApplication.AuthorizeRequest, ma sorprendentemente questo evento si attiva anche per le risorse che consentono l'accesso anonimo.

Qualche idea? Grazie per aver letto!

risposta

4

Creare un IPrincipal di bootleg e quindi è necessario utilizzarlo. Se l'entità bootleg ha accesso, è consentito l'accesso anonimo.

public static class AnonymousAccessCheck 
      { 
       public static bool IsAnonymousAccessAllowed(HttpRequest request) 
       { 
        // unfortunately checking if a page allows anonymous access is more complicated than you'd think(I think). 
        // here we have to create a "Fake" IPrincipal that will only ever have access to 
        // pages that allow anonymous access. That way if our fake principal has access, 
        // then anonymous access is allowed 

        UrlAuthorizationModule urlAuthorizationModule = new UrlAuthorizationModule(); 
        return UrlAuthorizationModule.CheckUrlAccessForPrincipal(request.Path, AnonymousPrincipal.Instance, request.RequestType); 
       } 

       private class AnonymousPrincipal : IPrincipal 
       { 
        private static AnonymousPrincipal _Instance; 
        public static AnonymousPrincipal Instance 
        { 
         get 
         { 
          if (_Instance == null) 
           _Instance = new AnonymousPrincipal(); 

          return _Instance; 
         } 
        } 

        private AnonymousPrincipal() 
        { 
         _Identity = new AnonymousIdentity(); 
        } 

        private readonly IIdentity _Identity; 

        #region IPrincipal Members 

        public IIdentity Identity 
        { 
         get { return _Identity; } 
        } 

        public bool IsInRole(string role) 
        { 
         return false; 
        } 

        #endregion 

        private class AnonymousIdentity : IIdentity 
        { 
         #region IIdentity Members 
         public string AuthenticationType 
         { 
          get { return string.Empty; } 
         } 

         public bool IsAuthenticated 
         { 
          get { return false; } 
         } 

         public string Name 
         { 
          get { return string.Empty; } 
         } 
         #endregion 
        } 
       } 
      } 
+0

+1 per creare un'istanza IPrincipal singleton. Pezzo di codice molto utile. Tuttavia, non ha bisogno di creare un'istanza di 'UrlAuthorizationModule'. È sufficiente utilizzare il metodo statico 'CheckUrlAccessForPrincipal'. –

0

Penso che se il server restituisce una risposta con 401 codice di stato non autorizzato, la risorsa potrebbe richiedere l'autorizzazione. Ma a volte il server può reindirizzare alla pagina di accesso, quindi questo metodo non è molto affidabile.

0

derp!

HttpContext.Current.SkipAuthorization 
+0

In realtà, non importa. Questo è sempre falso per le mie esclusioni di autorizzazione impostate in web.config. Solo le pagine come Login.aspx e WebResource.axd hanno questa proprietà impostata su true. Giù vota la mia risposta –

0

un approccio più diretto è il seguente:

var method = typeof(UrlAuthorizationModule).GetMethod("RequestRequiresAuthorization", BindingFlags.NonPublic | BindingFlags.Static); 
var requiresAuthentication = (Boolean)method.Invoke(null, new object[] { HttpContext.Current }); 

Prima di utilizzare questo, assicurarsi che il vostro sito web dispone di autorizzazioni per eseguire riflessione.

< Rant>

Non ho mai capito perché la pelle di Microsoft così tanto del loro API con "interno" (come questo metodo). Secondo me, se Microsoft dovesse esporre qualcosa internamente allora le probabilità sono di qualcuno, da qualche parte ne avrà bisogno.

</Rant>

7

Invece di creare un bootleg principal/identità si può semplicemente utilizzare un'identità generica.

public bool IsAnonymousAccessAllowed() 
{ 
    return UrlAuthorizationModule.CheckUrlAccessForPrincipal(Request.Path, new GenericPrincipal(new GenericIdentity(""), new string[0]), Request.RequestType); 
} 
Problemi correlati