我从Asp.Net Web API开始,这是我的问题:
我实现了一个自定义授权过滤器来检查我的邮件标题,以查找API密钥。基于此API密钥,我检索我的用户,然后我想看看他是否可以访问某些资源。我想要检查的资源ID是HTTP请求的参数。但是当我使用AuthorizationFilter方法时,操作参数列表为空。
我该怎么做?
如果我使用ActionFilter代替授权过滤器,我怎么能确定这是第一个执行的过滤器?在全球范围内,如何指定过滤器的执行顺序?
最后一个问题,是否可以在管道上添加一些我可以在任何过滤器上检索的数据?像会话商店这样但仅限于请求?
感谢您的回复
答案 0 :(得分:24)
授权属性在参数绑定运行之前运行,因此您不能(如您所见)使用ActionArguments
集合。相反,您需要将请求uri用于查询参数并为uri参数路由数据,如下所示。
//request at http://localhost/api/foo/id?MyValue=1
public class MyAuthorizationAttribute : AuthorizeAttribute
{
protected override bool IsAuthorized(HttpActionContext actionContext)
{
//will not work as parameter binding has not yet run
object value;
actionContext.ActionArguments.TryGetValue("id", out value);
//Will get you the resource id assuming a default route like /api/foo/{id}
var routeData = actionContext.Request.GetRouteData();
var myId = routeData.Values["id"] as string;
//uri is still accessible so use this to get query params
var queryString = HttpUtility.ParseQueryString(actionContext.Request.RequestUri.Query);
var myQueryParam = queryString["MyValue"];
//and so on
}
}
关于执行顺序:
使用FilterScope Enumeration ...范围为Global,Controller和Action,有3种不同的方法来指定过滤器的执行顺序。 AuthoriseAttribute
是“全局”,因此
指定Controller之前的操作。
如果您需要在这3个范围内指定执行顺序,那么您应该在这里阅读this blog article,您需要在其中实现FilterProvider
向管道添加一些数据:
在请求期间,此集合可用的请求上使用属性集合。
protected override bool IsAuthorized(HttpActionContext actionContext)
{
actionContext.Request.Properties.Add("__MYKEY__","MyValue");
//access this later in the controller or other action filters using
var value = actionContext.Request.Properties["__MYKEY__"];
}
答案 1 :(得分:1)
获取参数的另一种方法是Execute
参数的绑定。
try
{
var binding = actionContext.ActionDescriptor.ActionBinding;
var parameters = binding.ParameterBindings.OfType<ModelBinderParameterBinding>();
var newBinding = new HttpActionBinding(actionContext.ActionDescriptor, parameters.ToArray());
newBinding.ExecuteBindingAsync(actionContext, new CancellationToken());
var id = actionContext.ActionArguments["id"] as string;
}
catch
{
base.HandleUnauthorizedRequest(actionContext);
}
注意:您需要确保只过滤来自Request URI的参数,因为我注意到对预期来自Request的任何参数执行绑定正文将不再传递给实际操作。即那些参数将 null 。
这只是要注意你可以这样做,我建议使用GetRouteData()/RouteData
,因为它不太可能破坏ASP.NET MVC模型绑定的进一步流程。
var routeData = actionContext.ControllerContext.RouteData;
var id = routeData.Values["id"] as string;