【问题标题】:asp.net MVC 3 applying AuthorizeAttribute to areasasp.net MVC 3 将 AuthorizeAttribute 应用于区域
【发布时间】:2011-05-16 11:46:36
【问题描述】:

我目前正在编写一个 Admin MVC 3 站点,每个用户只能访问该站点的某些部分。

我站点的区域与用户角色相同,所以我想做的是将 AuthorizeAttribute 放在每个区域上,使用区域的名称作为角色中的参数。

到目前为止,当我对每个区域的检查进行硬编码时,我已经完成了这项工作,但我只想遍历所有区域并应用授权过滤器。 (我将其用作我的自定义 FilterProvider - http://www.dotnetcurry.com/ShowArticle.aspx?ID=578

到目前为止我的代码(“Gcm”是我的领域之一,也是一个角色):

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    // for all controllers, run AdminAuthorizeAttribute to make sure they're at least logged in
    filters.Add(ObjectFactory.GetInstance<AdminAuthorizeAttribute>());

    AdminAuthorizeAttribute gcmAuthroizeAttribute = ObjectFactory.GetInstance<AdminAuthorizeAttribute>();
    gcmAuthroizeAttribute.Roles = "Gcm";

    var provider = new FilterProvider();
    provider.Add(
        x =>
        x.RouteData.DataTokens["area"] != null && x.RouteData.DataTokens["area"].ToString() == "Gcm"
            ? gcmAuthroizeAttribute
            : null);
    FilterProviders.Providers.Add(provider);
}

有谁知道如何获取我的应用程序的所有区域,这样我就可以遍历它们,而不是对每个区域进行硬编码?

或者,如果有人对如何按区域进行授权有更好的了解,我们将不胜感激。

感谢您的帮助 萨安

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-3 filter asp.net-mvc-areas authorize-attribute


    【解决方案1】:

    您可以为每个区域制作一个基本控制器,并将授权属性放在基类上。这样您就可以为每个区域的基本控制器传递 area 参数。

    【讨论】:

      【解决方案2】:

      这是我创建的授权属性覆盖的示例。我需要我的授权函数来支持成员船的类型,所以你可能不想过多地进入函数的内部工作,但 AuthorizeCore 是主要逻辑发生的地方。就我而言,我正在对照实体数据上下文检查它。

      用法:

      [AjaxAuthorize(AjaxRole = "Administrators")]
      public JsonResult SaveAdministrativeUser(v.... )
      

      代码:

       public class AjaxAuthorizeAttribute : AuthorizeAttribute
          {
              private class HttpAuthorizeFailedResult : ActionResult
              {
                  public override void ExecuteResult(ControllerContext context)
                  {                
                      // Set the response code to 403.   Membership.Provider.Name == "UnitArchiveMembershipProvider"
                      context.HttpContext.Response.StatusCode = context.HttpContext. User.Identity is WindowsIdentity ?  401 : 403; 
                  }
              }
      
              public string AjaxRole { get; set;}
      
              public AjaxAuthorizeAttribute()
              {
                  AjaxRole = "Users";
              }
      
              protected override bool AuthorizeCore(HttpContextBase httpContext)
              {
                  if (string.IsNullOrEmpty(MvcApplication.Config.DBSettings.Database))
                  {
                      return true;
                  }
      
                  //When authorize parameter is set to false, not authorization should be performed.
                  UnitArchiveData db = DataContextFactory.GetWebRequestScopedDataContext<UnitArchiveData>(MvcApplication.Config.DBSettings.GetConnectionString());            
      
      
                  if (httpContext.User.Identity.IsAuthenticated)
                  {
                      login_data user = db.login_datas.Where(n => n.EmailAddress == httpContext.User.Identity.Name).FirstOrDefault();
                      if (user != null)
                      {
                          return user.cd_login_role.RoleName == "Administrators" || user.cd_login_role.RoleName == AjaxRole;
                      }
                  }
      
                  return false;
      
              }
      
              protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
              {
                  if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
                  {
                      //Ajax request doesn't return to login page, it just returns 403 error.
                      filterContext.Result = new HttpAuthorizeFailedResult();
                  }
                  else
                      base.HandleUnauthorizedRequest(filterContext);
              }
          }
      

      【讨论】:

      • 嗨,谢尔盖。感谢您的回复 - 但我已经创建了我的自定义 Authorize 属性,它工作正常。我只需要能够在每个领域中传递适当的角色。我不想将属性放在每个控制器上。我正在寻找可以在有人添加新区域时自动设置的东西。
      • 是的,看看我是怎么做的。 AjaxRole 变量被传递到自定义 AuthorizeAttribte。自动可能很难,但在函数头中添加 [AjaxAuthorize(AjaxRole = "Administrators")] 并不难,并且可以解决您的问题。
      • 但这确实意味着向项目添加代码的任何人(有些是第三方开发人员)都需要确保将正确的 Authorize 属性添加到控制器中。我正在寻找的是一种确保无论如何都使用正确授权的方法。
      • 这种方式不包括其他人必须遵循的命名约定吗?我的意思是你比我更清楚你需要什么,但这将是微软推荐使用 AuthorizeAttribute 的方式。
      • 并非如此——当我添加第三方区域时——其中一部分是添加角色。我认为如果我能得到一个站点中所有区域的列表,然后循环遍历它们,它会起作用。
      【解决方案3】:

      当我调查一个单独的问题时,我遇到了How to pass parameters to a custom ActionFilter in ASP.NET MVC 2?

      可以更改该属性示例以检查当前控制器的区域。

      public class CustomAuthorizeAttribute : AuthorizeAttribute
      {
          public override void OnAuthorization(AuthorizationContext filterContext)
          {
              RouteData routeData = filterContext.RouteData;
      
              // check if user is allowed on this page
              if (SessionFactory.GetSession().Contains(SessionKey.User))
              {
                  User user = (User)SessionFactory.GetSession().Get(SessionKey.User);
                  string thisArea = routeData.DataTokens["area"].ToString();
      
                  // if the user doesn't have access to this area
                  if (!user.IsInRole(thisArea))
                  {
                      HandleUnauthorizedRequest(filterContext);
                  }
              }
      
              // do normal OnAuthorization checks too
              base.OnAuthorization(filterContext);
          }
      }
      

      然后我将我的自定义授权属性应用于 Global.asax 中的所有控制器:

      public static void RegisterGlobalFilters(GlobalFilterCollection filters)
      {
          filters.Add(new HandleErrorAttribute());
          // for all controllers, run CustomAuthorizeAttribute to make sure they're at logged in and have access to area
          filters.Add(ObjectFactory.GetInstance<CustomAuthorizeAttribute>());
      }
      

      感谢所有回复的人

      萨恩

      【讨论】:

      • 警告:这不是安全的做法。我一直在研究这个领域,发现这不是一个可取的做法。区域是一个路由概念,但控制器可以被找到并被拾取即使没有指定区域Levi explains here
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-27
      • 2011-07-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多