我正在尝试使用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();
}
}所以我想,我也可以检查一下多个索赔值-
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”类型的合适构造函数。确保类型是具体的,并为公共构造函数的所有参数注册服务。
我认为这与注册服务没有任何关系,否则第一个版本就行不通。它似乎更琐碎/愚蠢,但我找不到它。
我做错什么了?
发布于 2020-03-29 15:22:28
这是关于如何传递参数以实例化目标IAuthorization类型(在本例中为Claims2Filter)。
如果Arguments属性(是一个对象数组)包含多个元素,那么每个元素都被认为是一个不同的参数,可以传递给目标IAuthorization类型的构造函数的一个不同的参数。换句话说,需要在Argument中的元素数和构造函数参数的数量之间进行一对一的映射。
因此,当Arguments包含两个Claim时,运行时实际上期望Claims2Filter具有以下构造函数-
public ClaimsFilter(Claim claim1, Claim claim2)
{
//
}若要使用接受单个参数(即索赔对象数组)的构造函数( IAuthorization类型的构造函数),Arguments属性( TypeFilterAttribute类型的)应该包含一个元素,该元素是Claim数组。
所以,下面的变化让一切都像预期的那样运转-
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 };
}
}我希望解释得足够清楚。
https://stackoverflow.com/questions/60895843
复制相似问题