自定义类型授权属性

时间:2016-08-12 10:09:19

标签: c# asp.net-web-api2

很难根据需要使用类型化构造函数参数自定义authorize属性。意图是避免魔术字符串角色(即"允许:经理:只读,拒绝:创建者:readwrite")。

我有什么:

public class AuthorizationAttribute : BaseAuthorizationAttribute
{
    public AuthorizationAttribute(params string[] authorizations) : base(authorizations) { }

    public override void OnActionExecuting(HttpActionContext filterContext)
    {       
        //I can't show BaseAuthorizationAttribute, what it does is, parse
        //supplied role strings([ALLOW/DENY:ROLE:SUBROLE]) separated by ':'
        //and add it to appropriate list DeniedRoles/AllowedRoles
        foreach (var denyRole in DeniedRoles)
        {
            if (Principal.HasAuthorization(denyRole.Role, denyRole.SubRole))
            {
                filterContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
                return;
            }
        }

        foreach (var allowRole in AllowedRoles)
        {
            if (Principal.HasAuthorization(allowRole.Role, allowRole.SubRole))
            {
                return;
            }
        }            
        filterContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
    }
}

用法:[Authorization("allow:manager:readonly", "deny:creator:readwrite")]

它只是 GREAT

我想要的是什么:我希望使用角色/子角色枚举代替角色字符串,以安全地使用此属性。

我尝试了什么: 我做了两个枚举:AuthorizationEnum - 拥有所有角色,AccessTypesEnum - 有子角色和[deny |允许]只是布尔。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public sealed class TypedAuthorizationAttribute : ActionFilterAttribute
{
    private AuthorizationEnum _authority { get; set; }
    private AccessTypesEnum _accessType { get; set; }
    private bool _allow { get; set; }
    public TypedAuthorizationAttribute(AuthorizationEnum authority, AccessTypesEnum accessType = AccessTypesEnum.ReadOnly, bool allow = true)
    {
        _authority = authority;
        _accessType = accessType;
        _allow = allow;
    }

    public override object TypeId { get { return this; } }

    public override void OnActionExecuting(HttpActionContext filterContext)
    {
        var principal = Thread.CurrentPrincipal as CorePrincipal;
        var hasAuthority = principal.HasAuthorization(_authority, _accessType);

        if (hasAuthority && _allow)
        {                
            return;
        }            
        filterContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
        filterContext.Response.ReasonPhrase = _authority.ToString() +":"+ _accessType.ToString();
    }
}

用法:[TypedAuthorization(AuthorizationEnum.AppealManager)]

对于单个角色,它可以完美地工作。但是对于角色列表来说,这对我来说是个噩梦。事实上,我想要ORing多个角色:

[TypedAuthorization(AuthorizationEnum.AppealManager), TypedAuthorization(AuthorizationEnum.ManageAppeals)]这样的用法无法解决我的问题,因为我想要" AppealManager" " ManageAppeals"应用实体可以访问的用户。

此外,我没有成功尝试(后来我知道,规范有limited valid attribute parameter types):

  • 创建元组(好吧,我发现这个数据结构很自然,符合我的需要) 个人角色(角色,子角色,允许)
  • 在构造函数参数上发送多个角色元组。

属性构造函数:

public TypedAuthorizationAttribute(params Tuple<AuthorizationEnum, AccessTypesEnum, bool>[] authorities){}

用法:[TypedAuthorization(Tuple.Create(AuthorizationEnum.AppealManager, AccessTypesEnum.ReadWrite, true), Tuple.Create(AuthorizationEnum.ManageAppeals, AccessTypesEnum.ReadOnly, false)]

希望你们明白我的问题。我被困在这里,有任何解决方法可以解决这个问题吗?任何建议将不胜感激。

0 个答案:

没有答案