9

Abbiamo un'applicazione intranet ASP.NET MVC 4. Stiamo usando l'autenticazione di Windows e quell'aspetto funziona bene. Vengono utilizzate le credenziali dell'utente e possiamo accedere a tali credenziali dall'app Web.Ibrido di autenticazione di Windows e autenticazione dei moduli in ASP.NET MVC 4

Ciò che vogliamo veramente è una sorta di modalità ibrida, tuttavia. Vogliamo ottenere le credenziali dell'utente dal browser, ma vogliamo anche verificare che l'utente si trovi nel nostro database dell'applicazione. Se l'utente è nel database, possono semplicemente continuare. Se non lo sono, vogliamo reindirli a una pagina che richiede credenziali alternative. Quello che sto facendo ora è, in Global.asax.cs, ho un metodo Application_AuthenticateRequest e sto verificando se l'utente è autenticato. Se lo sono e le loro informazioni sui cookie non riflettono il fatto che sono collegati al sistema, quindi li accedo e configuro alcuni cookie con informazioni sull'utente. Se non sono autenticati, li reindirizzo a una pagina di accesso. Non possiamo utilizzare i ruoli di Active Directory per motivi legati ai criteri aziendali, quindi è necessario utilizzare il database per l'autenticazione aggiuntiva.

Suppongo che Application_AuthenticateRequest non sia il posto giusto per farlo, ma forse lo è. Ma fondamentalmente abbiamo bisogno di un posto dove filtrare le richieste di autenticazione. Ma in aggiunta questa implementazione mi porta ad un altro problema:

Abbiamo alcuni URL nella nostra app che consentono l'accesso anonimo. Ho aggiunto i tag <location> al web.config per questi. Il problema è che, quando vengono effettuate chiamate anonime, arriva a Application_AuthenticateRequest e tenta di registrare l'utente nel DB. Ora, posso aggiungere il codice a Application_AuthenticateRequest per gestire questi URL e questo è attualmente il mio piano, ma se sto scrivendo e Application_AuthenticateRequest non è il posto giusto per farlo, allora preferirei capirlo ora più tardi.

risposta

5

È necessario utilizzare i filtri di azione per questo scopo. È possibile estendere l'AuthorizeAttribute in questo modo:

public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    private UnitOfWork _unitOfWork = new UnitOfWork(); 

    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     var isAuthorized = false; 
     var username = httpContext.User.Identity.Name; 
     // Some code to find the user in the database... 
     var user = _unitOfWork.UserRepository.Find(username); 
     if(user != null) 
     { 
      isAuthorized = true; 
     } 


     return isAuthorized; 
    } 

    public override void OnAuthorization(AuthorizationContext filterContext) 
    {    
     if (filterContext == null) 
     { 
      throw new ArgumentNullException("filterContext"); 
     } 

     if (AuthorizeCore(filterContext.HttpContext)) 
     { 
      SetCachePolicy(filterContext); 
     } 
     else 
     { 
      // If not authorized, redirect to the Login action 
      // of the Account controller... 
      filterContext.Result = new RedirectToRouteResult(
      new System.Web.Routing.RouteValueDictionary { 
       {"controller", "Account"}, {"action", "Login"} 
      } 
     );    
     } 
    } 

    protected void SetCachePolicy(AuthorizationContext filterContext) 
    { 
     // ** IMPORTANT ** 
     // Since we're performing authorization at the action level, 
     // the authorization code runs after the output caching module. 
     // In the worst case this could allow an authorized user 
     // to cause the page to be cached, then an unauthorized user would later 
     // be served the cached page. We work around this by telling proxies not to 
     // cache the sensitive page, then we hook our custom authorization code into 
     // the caching mechanism so that we have the final say on whether a page 
     // should be served from the cache. 
     HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache; 
     cachePolicy.SetProxyMaxAge(new TimeSpan(0)); 
     cachePolicy.AddValidationCallback(CacheValidationHandler, null /* data */); 
    } 

    public void CacheValidationHandler(HttpContext context, 
             object data, 
             ref HttpValidationStatus validationStatus) 
    { 
     validationStatus = OnCacheAuthorization(new HttpContextWrapper(context)); 
    } 
} 

Quindi, è possibile utilizzare questo attributo a livello di controller o il livello d'azione come questo:

[MyAuthorize] 
public ActionResult SomeAction() 
{ 
    // Code that is supposed to be accessed by authorized users only 
} 
+0

mi piace questa soluzione, ma ho ancora ottenere 401 errori sul metodi di controllo che dovrebbero consentire a chiunque. In questo caso particolare, lo chiamo da una chiamata C# 'HttpWebRequest.GetResponse()'. 'DebugController.FlushCaches()' ha [AllowAnonymous] e nel 'web.config' ho un tag' 'per' Debug/FlushCaches' che ha ''. Ma quando il mio 'HttpWebRequest' chiama, ho un 401. – Pete

+0

Utilizzare questo come tag: ' ' – ataravati

+0

http://stackoverflow.com/questions/15087755/use-anonymous-authentication-in-mvc4-on-single-controller-when-the-whole-applica – ataravati

Problemi correlati