如果我想使用ASP.NET MVC4创建ApiKey受限资源,我应该使用IAuthorizationFilter吗?

Pur*_*ome 20 .net c# authorization asp.net-mvc-4

我有一些简单的路由,我希望通过一个简单的查询字符串参数进行限制.如果密钥不正确或未提供,那么我希望抛出一个NotAuthorizedException.

请不要建议我使用WebApi或等效 - 我不能在这种情况下使用.

所以我不确定我是应该实现IAuthorizationFilter或实现一个IActionFilter甚至是别的东西.

我的代码逻辑?

  • 检查查询字符串是否有关键.
  • 检查我的RavenDb(存储库)以查找具有该键/值的用户.

如果他们没有通过任何这些检查,那么扔掉NotAuthorizedException.

我假设我会用这个过滤器装饰我的动作方法.我还假设我需要将我的存储库传递给这个动作方法吗?

有什么建议吗?

Dar*_*rov 34

所以我不确定我是应该实现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();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您想在自定义操作过滤器中使用依赖项注入,您可以查看following article可以在其中实现自定义过滤器提供程序(IFilterProvider).您可以使用可在控制器操作上使用的标记属性,然后让此自定义过滤器提供程序只查看操作是否使用此标记属性进行修饰并应用自定义授权过滤器.

例如:

public class MyAuthorizeAttribute: Attribute
{

}
Run Code Online (Sandbox Code Playgroud)

并且您的授权过滤器只会实现IAuthorizationFilter,它不会是FilterAttribute:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你将拥有自定义过滤器提供程序:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

将在您的注册Application_Start:

FilterProviders.Providers.Add(new MyFilterProvider());
Run Code Online (Sandbox Code Playgroud)