2009-09-28 57 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