9

Mamy aplikację intranetową ASP.NET MVC 4. Używamy uwierzytelniania systemu Windows i ten aspekt działa dobrze. Używane są poświadczenia użytkownika, a my uzyskujemy dostęp do tych danych uwierzytelniających z aplikacji internetowej.Hybrydowe uwierzytelnianie Windows i uwierzytelnianie formularzy w ASP.NET MVC 4

Tym, czego naprawdę chcemy, jest jednak tryb hybrydowy. Chcemy uzyskać dane uwierzytelniające użytkownika z przeglądarki, ale chcemy również sprawdzić, czy użytkownik znajduje się w naszej bazie danych aplikacji. Jeśli użytkownik jest w bazie danych, może po prostu kontynuować. Jeśli nie, chcemy przekierować je na stronę z prośbą o podanie alternatywnych danych uwierzytelniających. Co teraz robię, to w Global.asax.cs, mam metodę Application_AuthenticateRequest i sprawdzam, czy użytkownik jest uwierzytelniony. Jeśli są, a ich pliki cookie nie odzwierciedlają faktu, że są zalogowane do systemu, to loguję je i konfiguruję pliki cookie z informacjami o użytkowniku. Jeśli nie zostaną uwierzytelnione, przekierowuję je na stronę logowania. Nie możemy używać ról AD z powodów związanych z polityką firmy, więc musimy użyć bazy danych do dodatkowego uwierzytelnienia.

Zgaduję, że Application_AuthenticateRequest nie jest odpowiednim miejscem, ale może tak jest. Ale w zasadzie potrzebujemy miejsca do filtrowania żądań uwierzytelnienia. Ale dodatkowo ta implementacja prowadzi mnie do innego problemu:

Mamy pewne adresy URL w naszej aplikacji, które umożliwiają anonimowy dostęp. Dodałem tagi <location> do pliku web.config. Problem polega na tym, że w przypadku anonimowych połączeń do nich, dostaje się do Application_AuthenticateRequest i próbuje zalogować użytkownika do DB. Teraz mogę dodać kod do Application_AuthenticateRequest, aby obsłużyć te adresy URL i to jest obecnie mój plan, ale jeśli mam pisać i Application_AuthenticateRequest nie jest to miejsce do robienia tego, wtedy wolałbym to rozgryźć teraz niż później.

Odpowiedz

5

Do tego celu należy użyć filtrów akcji. Można rozszerzyć AuthorizeAttribute tak:

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)); 
    } 
} 

Następnie można użyć tego atrybutu na poziomie kontrolera lub poziomu działań takich jak to:

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

Lubię to rozwiązanie, ale ja wciąż dostać 401 błędów na metody kontrolerów, które powinny umożliwić każdemu. W tym konkretnym przypadku wywołuję go z wywołania C# 'HttpWebRequest.GetResponse()'. 'DebugController.FlushCaches()' ma [AllowAnonymous] iw 'web.config' mam' '' tag dla 'Debug/FlushCaches', który ma' '. Ale kiedy mój 'HttpWebRequest' wzywa go, otrzymuję 401. – Pete

+0

użyć tego jako tagu: ' ' – ataravati

+0

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

Powiązane problemy