9

我們有一個ASP.NET MVC 4 Intranet應用程序。我們正在使用Windows身份驗證,該方面工作正常。使用用戶的憑證,我們可以從Web應用程序訪問這些憑證。在ASP.NET MVC中混合使用Windows身份驗證和表單身份驗證4

但是,我們真正想要的是某種混合模式。我們希望從瀏覽器獲取用戶的憑據,但我們也想驗證用戶是否在我們的應用程序的數據庫中。如果用戶在數據庫中,那麼他們可以繼續。如果它們不是,我們希望將它們重定向到要求備用憑證的頁面。我現在正在做的是,在Global.asax.cs,我有一個Application_AuthenticateRequest方法,我正在檢查用戶是否通過身份驗證。如果他們和他們的cookie信息沒有反映他們登錄到系統的事實,那麼我將他們登錄並設置一些有關用戶信息的cookie。如果他們沒有通過身份驗證,我會將他們重定向到登錄頁面。由於涉及公司政策的原因,我們無法使用AD角色,因此我們需要使用數據庫進行額外的身份驗證。我想Application_AuthenticateRequest不是做這個的地方,但也許是。但我們基本上需要一個地方來過濾認證請求。但是另外這個實現導致我另一個問題:

我們的應用程序中有一些URL允許匿名訪問。我已經爲這些web.config添加了<location>標籤。問題是,當匿名呼叫進入這些時,它會到達Application_AuthenticateRequest並嘗試將用戶登錄到數據庫中。現在,我可以將代碼添加到Application_AuthenticateRequest中來處理這些URL,這是我目前的計劃,但如果我編寫並且Application_AuthenticateRequest不是要執行此操作的位置,那麼我寧願將其計算出來,而不是稍後。

回答

5

您需要爲此使用動作過濾器。您可以擴展AuthorizeAttribute這樣的:

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

然後,您可以在控制器級別或操作級別這樣使用這個屬性:

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

我喜歡這個解決辦法,但我仍然得到401錯誤控制器方法應該允許任何人。在這種特殊情況下,我從C#'HttpWebRequest.GetResponse()'調用它來調用它。 'DebugController.FlushCaches()'具有[AllowAnonymous],並且在'web.config'中,我有一個'「的'Debug/FlushCaches'的標籤''。但是,當我'HttpWebRequest'調用它,我得到一個401 – Pete

+0

使用此爲您標籤: '<位置路徑= 「調試/ FlushCaches」> <授權> <允許用戶= 「*」/ > ' – ataravati

+0

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

相關問題