【问题标题】:C# Attributes : Using enum constants as input parametersC# 属性:使用枚举常量作为输入参数
【发布时间】:2012-09-09 18:32:13
【问题描述】:

我正在尝试为我的 MVC 应用程序实现一种新的基于权限的访问方法;我们有几个权限组,每个组都包含一个权限列表。例如,我们有 Invoices 权限组,其中包含 CreateInvoice,RemoveInvoice,etc 权限键。

在这种方法中,每个 mvc Action 都应该需要特定的执行权限。我正在尝试通过 CustomAttributes 来做到这一点,就像这样:

public class InvoiceController : Controller
    {
        [RequirePermission(Permissions.Invoices.CreateInvoice)]
        public ActionResult Create()
        {
            return View();
        }
    }

为了让开发人员更容易记住不同的权限组和权限密钥,我正在尝试创建一个预定义的权限列表,该列表应该是权限组和权限密钥的组合。但由于限制在 C# 中使用属性参数 我还不能让它工作。 (我不想做一个超大的枚举器并将所有权限密钥放在那里

我的最后一次尝试是为每个权限组创建一个枚举器,然后在其中将权限键定义为枚举常量:

public class PermissionEnums
{
    [PermissionGroup(PermissionGroupCode.Invoice)]
    public enum Invoices
    {
        CreateInvoice = 1,
        UpdateInvoice = 2,
        RemoveInvoice = 3,
        ManageAttachments = 4
    }

    [PermissionGroup(PermissionGroupCode.UserAccounts)]
    public enum UserAccounts
    {
        Create = 1,
        ChangePassword = 2
    }
}

如您所见,我们在这里有代码组合,使用 PermissionGroup 属性指定的权限组密钥和每个枚举常量上指定为数字代码的权限密钥代码。

RequirePermission 属性定义如下:

public class RequirePermissionAttribute : Attribute
{
    private Enum _Permission;

    public RequirePermissionAttribute(Enum Permission)
        : base()
    {
        _Permission = Permission;
    }
}

但问题是Enum 类型的对象不能用作属性参数。

感谢任何建议/想法

【问题讨论】:

    标签: c# asp.net-mvc custom-attributes access-control


    【解决方案1】:

    我找到了解决方案,唯一需要更改的是构造参数的类型。而不是使用Enum,你必须使用object

    public class RequirePermissionAttribute : AuthorizeAttribute
    {
        private object _Permission;
    
        public RequirePermissionAttribute(object Permission)
            : base()
        {
            _Permission = Permission;
        }
    }
    

    这是完整的代码:

    /***************** Permission Groups And Keys *****************/
    public static class Permissions
    {
        [PermissionGroup(PermissionGroupCode.Invoice)]
        public enum Invoices
        {
            CreateInvoice = 1,
            UpdateInvoice = 2,
            RemoveInvoice = 3,
            ManageAttachments = 4
        }
    
        [PermissionGroup(PermissionGroupCode.UserAccounts)]
        public enum UserAccounts
        {
            Create = 1,
            ChangePassword = 2
        }
    }
    
    public enum PermissionGroupCode
    {
        Invoice = 1,
        UserAccounts = 2,
        Members = 3
    }
    
    /***************** Attributes & ActionFilters *****************/
    
    [AttributeUsage(AttributeTargets.Enum)]
    public class PermissionGroupAttribute : Attribute
    {
        private PermissionGroupCode _GroupCode;
        public PermissionGroupCode GroupCode
        {
            get
            {
                return _GroupCode;
            }
        }
    
        public PermissionGroupAttribute(PermissionGroupCode GroupCode)
        {
            _GroupCode = GroupCode;
        }
    }
    
    
    public class RequirePermissionAttribute : AuthorizeAttribute
    {
        private object _RequiredPermission;
    
        public RequirePermissionAttribute(object RequiredPermission)
            : base()
        {
            _RequiredPermission = RequiredPermission;
        }
    
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            var permissionGroupMetadata = (PermissionGroupAttribute)_RequiredPermission.GetType().GetCustomAttributes(typeof(PermissionGroupAttribute), false)[0];
    
            var groupCode = permissionGroupMetadata.GroupCode;
            var permissionCode = Convert.ToInt32(_RequiredPermission);
    
            return HasPermission(currentUserId, groupCode, permissionCode);
        }
    }
    

    【讨论】:

      【解决方案2】:

      我认为这不可能我试图做你的事但失败了:/对不起。

      操作权限应与 Authorize 一起使用,您可以编写自己的 ovveride,如下所示:

          [AttributeUsage(AttributeTargets.All)]
          public sealed class CustomAuthorizeAttribute : AuthorizeAttribute
          {
      
         protected override bool AuthorizeCore(HttpContextBase httpContext)
          {
              if (httpContext == null)
                  throw new ArgumentNullException("httpContext");
      
              //Its a piece of code from my app you can modify it to suit your needs or use the base one
              if (!new CustomIdentity(httpContext.User.Identity.Name).IsAuthenticated)
              {
                  return false;
              }
      
              return true;
          }
      
          protected override void HandleUnauthorizedRequest(AuthorizationContext    filterContext)
          {
              base.HandleUnauthorizedRequest(filterContext);
      
           }
      
      }
      

      那么关于你的行动:

      [CustomAuthorizeAttribute(Roles = "FE")]
      public ActionResult Index()
      {
          return RedirectToAction("Index", "Documents");
      }
      

      但是,它仍然是您使用的字符串,并且要使其正常工作,您需要将其与自定义角色提供程序结合使用。很麻烦,但我认为值得。

      【讨论】:

      • 是的,我已经做到了,但我的问题不是创建属性(ActionFilter 属性)来检查用户权限。我只需要一种更好的方法(比使用纯字符串键)来创建预定义的权限常量。
      猜你喜欢
      • 1970-01-01
      • 2011-01-21
      • 2019-12-02
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-10
      相关资源
      最近更新 更多