Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如果我希望使用ASP.NET MVC4创建ApiKey受限资源,是否应该使用IAuthorizationFilter?_C#_.net_Asp.net Mvc 4_Authorization - Fatal编程技术网

C# 如果我希望使用ASP.NET MVC4创建ApiKey受限资源,是否应该使用IAuthorizationFilter?

C# 如果我希望使用ASP.NET MVC4创建ApiKey受限资源,是否应该使用IAuthorizationFilter?,c#,.net,asp.net-mvc-4,authorization,C#,.net,Asp.net Mvc 4,Authorization,我有几个简单的路由,我希望通过一个简单的查询字符串参数来限制它们。如果密钥不正确或未提供,则我希望抛出NotAuthorizedException 请不要建议我使用WebApi或等价物-我现在还不能在这种情况下使用 因此,我不确定是应该实现IAuthorizationFilter还是实现IActionFilter或者其他什么 我的代码逻辑 检查查询字符串以查找密钥 检查my RavenDb(存储库)中是否有具有该键/值的用户 如果他们没有通过任何一项检查,则抛出NotAuthorizedEx

我有几个简单的路由,我希望通过一个简单的查询字符串参数来限制它们。如果密钥不正确或未提供,则我希望抛出
NotAuthorizedException

请不要建议我使用WebApi或等价物-我现在还不能在这种情况下使用

因此,我不确定是应该实现
IAuthorizationFilter
还是实现
IActionFilter
或者其他什么

我的代码逻辑

  • 检查查询字符串以查找密钥
  • 检查my RavenDb(存储库)中是否有具有该键/值的用户
如果他们没有通过任何一项检查,则抛出
NotAuthorizedException

我假设我会用这个过滤器装饰我的动作方法。我还假设我还需要将我的存储库传递到这个操作方法中

有什么建议吗

因此,我不确定是否应该实现IAuthorizationFilter或 实现一个IActionFilter甚至其他东西

您应该实现一个
IAuthorizationFilter

public class MyAuthorizeAttribute: FilterAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        var key = filterContext.HttpContext.Request.QueryString["param_name"];
        if (!IsValid(key))
        {
            // Unauthorized!
            filterContext.Result = new HttpUnauthorizedResult();
        }
    }

    private bool IsValid(string key)
    {
        // You know what to do here => go hit your RavenDb
        // and perform the necessary checks
        throw new NotImplementedException();
    }
}
如果您想在自定义操作筛选器中使用依赖项注入,您可以查看可以在其中实现自定义筛选器提供程序(
IFilterProvider
)。您可以有一个可用于控制器操作的标记属性,然后让此自定义筛选器提供程序只需查看该操作是否用此标记属性修饰并应用自定义授权筛选器即可

例如:

public class MyAuthorizeAttribute: Attribute
{

}
您的授权筛选器将只实现
iaauthorizationfilter
,而不是
filteratAttribute

public class MyAuthorizationFilter: IAuthorizationFilter
{
    private readonly ISomeRepository repository;
    public class MyAuthorizationFilter(ISomeRepository repository)
    {
        this.repository = repository;
    }

    public void OnAuthorization(AuthorizationContext filterContext)
    {
        var key = filterContext.HttpContext.Request.QueryString["param_name"];
        if (!IsValid(key))
        {
            // Unauthorized!
            filterContext.Result = new HttpUnauthorizedResult();
        }
    }

    private bool IsValid(string key)
    {
        // You know what to do here => go hit your RavenDb
        // and perform the necessary checks
        throw new NotImplementedException();
    }
}
然后您将拥有自定义筛选器提供程序:

public class MyFilterProvider : IFilterProvider
{
    public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        if (actionDescriptor.GetCustomAttributes(typeof(MyAuthorizeAttribute), true).Any())
        {
            var filter = DependencyResolver.Current.GetService<MyAuthorizationFilter>();
            yield return new Filter(filter, FilterScope.Global);
        }

        yield break;
    }
}

谢谢你,达林!我注意到您使用了属性注入(我想这就是它的名称)而不是构造函数注入-有什么原因我不能在
MyAuthorizationFilter
类中这样做吗。。并让
MyAuthorizationFilter
也继承
FilterAttribute
?那么我就只有1个类,而不是2个。不,它使用构造函数注入。这就是
DependencyResolver
MyFilterProvider
中所做的。我假设您不能使用单个类,因为框架没有使用DependencyResolver构造属性,因此,您不能用它来装饰您的操作,因为它需要一个
存储库
传递给构造函数,并且您没有可用的存储库。有没有更好的方法在属性上进行构造函数注入,因为此实现将很难执行类似于
[MyAuthorize(ErrorMessage=“Sad panda”)]
@ajbea的操作,即使您可以使用参数创建属性,然后将它们设置为内部属性,并从authorizationFilter中获取属性以访问其属性/字段。使用
filterContext.ActionDescriptor.GetCustomAttributes(typeof(YourClass),true.Cast()以获取属性。如果你有一个专门的项目,内部范围是有用的;除此之外,只需制作getter。
FilterProviders.Providers.Add(new MyFilterProvider());