【问题标题】:Checking claims with IAuthorizationFilter - "A suitable constructor for type could not be located"使用 IAuthorizationFilter 检查声明 - “找不到合适的类型构造函数”
【发布时间】:2020-07-08 18:33:27
【问题描述】:

我正在尝试使用 IAuthorizationFilter 实现来检查声明。使用以下代码,它工作得很好 -

    public class ClaimsAttribute : TypeFilterAttribute
    {
        public ClaimsAttribute(string claimType, string claimValue) : base(typeof(ClaimsFilter))
        {
            this.Arguments = new object[] { new Claim(claimType, claimValue) };
        }
    }

    public class ClaimsFilter : IAuthorizationFilter
    {
        private readonly Claim _claim;

        public ClaimsFilter(Claim claim)
        {
            _claim = claim;
        }

        public void OnAuthorization(AuthorizationFilterContext context)
        {
            var hasClaim = context.HttpContext.User.Claims.Any(p => p.Type == _claim.Type && p.Value == _claim.Value);
            if (!hasClaim)
            {
                context.Result = new ForbidResult();
            }
        }
    }

    public class DocumentController : Controller
    {
        [Claims(AppClaimTypes.Permission, "CanReadDocument")]
        [HttpGet]
        public ActionResult GetDocument()
        {
            return View();
        }
    }

所以我想,我也可以检查多个 Claim 值 -

    public class Claims2Attribute : TypeFilterAttribute
    {
        public Claims2Attribute(string claimType, params string[] claimValues) : base(typeof(Claims2Filter))
        {
            this.Arguments = new object[claimValues.Length];
            for (int i = 0; i < claimValues.Length; i++)
            {
                this.Arguments[i] = new Claim(claimType, claimValues[i]);
            }
        }
    }

    public class Claims2Filter : IAuthorizationFilter
    {
        private readonly Claim[] _claims;

        public Claims2Filter(Claim[] claims)
        {
            _claims = claims;
        }

        public void OnAuthorization(AuthorizationFilterContext context)
        {
            bool hasClaim = false;
            foreach (var item in _claims)
            {
                hasClaim = context.HttpContext.User.Claims.Any(p => p.Type == item.Type && p.Value == item.Value);
                if (hasClaim)
                    break;
            }

            if (!hasClaim)
            {
                context.Result = new ForbidResult();
            }
        }
    }

    public class DocumentController : Controller
    {
        [Claims2(AppClaimTypes.Permission, "CanReadSecretDocument", "SecretAccess")]
        [HttpGet]
        public ActionResult GetSecretDocument()
        {
            return View();
        }
    }

但现在它会抛出错误 -

InvalidOperationException:适合类型的构造函数 找不到“AuthorizationFilterTest.Claims2Filter”。确保 类型是具体的,并且为所有参数注册了服务 一个公共构造函数。

我认为它与注册服务无关,否则第一个版本将无法正常工作。这似乎更琐碎/愚蠢,但我找不到它。

我做错了什么?

【问题讨论】:

    标签: c# asp.net-core constructor iauthorizationfilter


    【解决方案1】:

    它是关于如何传递参数以实例化目标IAuthorization 类型(在本例中为Claims2Filter)。

    如果Arguments 属性(它是一个对象数组)包含多个元素,则每个元素都被视为一个不同的参数,以传递给目标IAuthorization 类型的构造函数的不同参数。也就是说,Argument中的元素个数和构造函数参数个数需要一一对应。

    所以,当Arguments 包含两个Claim 对象时,运行时实际上期望Claims2Filter 具有以下构造函数-

        public ClaimsFilter(Claim claim1, Claim claim2)
        {
                //
        }
    

    要使用接受单个参数的构造函数(IAuthorization 类型),该参数是 Claim 对象的数组,Arguments 属性(TypeFilterAttribute 类型)应该包含一个数组元素声明对象。

    因此,以下更改使一切按预期工作 -

        public class Claims2Attribute : TypeFilterAttribute
        {
            public Claims2Attribute(string claimType, params string[] claimValues) : base(typeof(Claims2Filter))
            {
                var claims = new Claim[claimValues.Length];
                for (int i = 0; i < claimValues.Length; i++)
                {
                    claims[i] = new Claim(claimType, claimValues[i]);
                }
    
                this.Arguments = new object[] { claims };
            }
        }
    

    我希望解释足够清楚。

    【讨论】:

    • 这个解释真的很好,谢谢。完美运行。
    猜你喜欢
    • 2020-10-01
    • 2019-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多