2009-09-28 100 views
3

我得出結論,我需要拋棄ASP.NET Membership(出於原因列表)。因此,非常非常困惑的身份驗證在asp.net mvc

現在真的我唯一需要看到的就是創建一個cookie(由Form Authentication完成),自定義方法進行身份驗證(完成),最後根據它們是否已登錄或按角色進行驗證。

我被困在最後一個。

我想重寫Authorize(屬性),但我不知道如何做到這一點。我看了很多例子,然後每個例子看起來都不一樣。我不知道他們爲什麼這樣做,或者我應該使用哪一個。

有些教程似乎在AuthorizeCore中進行身份驗證,有些教程在OnAuthentication中執行身份驗證。

一些使用一些AuthorizationContext的東西,然後調用這個基類。

base.OnAuthorization(filterContext); 

有些似乎在緩存中。

我想要的是內置的所有功能都已經連接到我的自定義表格。就像我將擁有自己的角色表一樣。我需要告訴它這是在拉東西

此外,我不知道如何做到這一點還是如何裝飾標籤這樣

[Authorize(Roles="test")] 

參考文獻: - 。 http://darioquintana.com.ar/blogging/tag/aspnet-mvc/ asp.net mvc Adding to the AUTHORIZE attribute http://davidhayden.com/blog/dave/archive/2009/04/09/CustomAuthorizationASPNETMVCFrameworkAuthorizeAttribute.aspx

編輯

這是我現在有。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)] 
    public sealed class AuthorizeAttributeCustom : AuthorizeAttribute 
    { 

     public string Roles { get; set; } 


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

     public override void OnAuthorization(AuthorizationContext filterContext) 
     { 

      if (filterContext == null) 
      { 
       throw new ArgumentNullException("filterContext"); 
      } 

      if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
      { 
       // auth failed, redirect to login page 
       filterContext.Result = new HttpUnauthorizedResult(); 
       return; 
      } 

      DataClasses1DataContext test = new DataClasses1DataContext(); 
      var name = filterContext.HttpContext.User.Identity.Name; 
      var user = test.User2s.Where(u => u.userName == name).FirstOrDefault(); 
      var role = test.Roles.Where(u => u.UserId == user.userId).Select(u => u.Role1).FirstOrDefault(); 

      string[] split = Roles.Split(','); 

      if (split.Contains(role) == true) 
      { 
       // is authenticated and is in the required role 
       SetCachePolicy(filterContext); 
       return; 
      } 
      filterContext.Result = new HttpUnauthorizedResult(); 
     } 

     private 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(CacheValidateHandler, null /* data */); 
     } 
    } 

出站在問題

  1. 爲什麼封了?如果密封 是否不會讓單元 測試更難?
  2. 什麼是filterContext?
  3. 爲什麼沒有使用AuthorizeCore?只有 OnAuthentication?
  4. 什麼是緩存引用?像 它緩存的角色?或者頁面? 我不能告訴調試器它 似乎運行代碼每個單獨 時間。

  5. 緩存是否安全?

  6. 總的來說這是安全的(即無孔 在它被explioted-有點擔心 我會搞砸的東西了,並有 在我的網站一些重大孔)。

回答

2

這是一個自定義屬性,它可以像你想要的那樣工作;使用Enum作爲角色類型並自己使用Cookie創建,這允許存儲角色。

使用

[AuthorizeAttributeCustom(RoleRequired = GoodRoles.YourRoleTypeHere)] 

屬性代碼:

//http://stackoverflow.com/questions/977071/redirecting-unauthorized-controller-in-asp-net-mvc/977112#977112 
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)] 
    public sealed class AuthorizeAttributeCustom : AuthorizeAttribute 
    { 

     /// <summary> 
     /// The name of the view to render on authorization failure. Default is "Error". 
     /// </summary> 
     public string ViewName { get; set; } 
     public ViewDataDictionary ViewDataDictionary { get; set; } 
     public DeniedAccessView DeniedAccessView { get; set; } 

     private GoodRoles roleRequired = GoodRoles.None; 
     public GoodRoles RoleRequired { get{ return roleRequired;} set{ roleRequired = value;} } // this may evolve into sets and intersections with an array but KISS 

     public AuthorizeAttributeCustom() 
     { 
      ViewName = "DeniedAccess"; 
      DeniedAccessView = new DeniedAccessView 
            { 
             FriendlyName = "n/a", 
             Message = "You do not have sufficient privileges for this operation." 
            }; 
      ViewDataDictionary = new ViewDataDictionary(DeniedAccessView); 
     } 

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


     public override void OnAuthorization(AuthorizationContext filterContext) 
     { 

      if (filterContext == null) 
      { 
       throw new ArgumentNullException("filterContext"); 
      } 

      if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
      { 
       // auth failed, redirect to login page 
       filterContext.Result = new HttpUnauthorizedResult(); 
       return; 
      } 

      if (RoleRequired == GoodRoles.None || filterContext.HttpContext.User.IsInRole(RoleRequired.ToString())) 
      { 
       // is authenticated and is in the required role 
       SetCachePolicy(filterContext); 
       return; 
      } 

      filterContext.Result = new ViewResult { ViewName = ViewName, ViewData = ViewDataDictionary }; 
     } 

     private 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(CacheValidateHandler, null /* data */); 
     } 


    } 

你必須明確地添加你的角色要權威性的cookie和閱讀他們回到基地控制器說。我的實施有其他細節,你可能不想這麼也許最好在這裏讀:http://ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html

+0

你能解釋這一點嗎?像什麼是chache?這對於頁面還是隻是角色? filterContext是什麼? – chobo2 2009-09-28 17:18:08

+0

我也是通過枚舉傳遞這個唯一的方式?我無法讓它看起來像內置的?由於我不確定這將如何影響單元測試?現在我看看標籤是否在那裏,並檢查他們的角色字符串包含。如果它包含我期望的角色,那麼它就會通過。另外我注意到它也沒有使用AuthorizeCore方法。爲什麼不? – chobo2 2009-09-28 17:47:43

+0

也是現在這條線的方式「filterContext.HttpContext.User.IsInRole(RoleRequired.ToString())」從哪裏拉動角色? VS2008 Intellisense甚至沒有IsInRole的東西。我會想,我將不得不這樣做與數據庫請求。 – chobo2 2009-09-28 17:49:46