25

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

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

所以我不确定我是否应该实施一个IAuthorizationFilter或实施一个IActionFilter甚至其他东西。

我的代码逻辑?

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

如果他们未能通过任何这些检查,则抛出NotAuthorizedException.

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

请问有什么建议吗?

4

1 回答 1

42

所以我不确定我是否应该实施 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();
    }
}

如果您想在您的自定义操作过滤器中使用依赖注入,您可以查看following article您可以在其中实现自定义过滤器提供程序 ( IFilterProvider)。您可以有一个标记属性,您可以在控制器操作上使用它,然后让这个自定义过滤器提供程序简单地查看该操作是否用这个标记属性修饰并应用自定义授权过滤器。

例如:

public class MyAuthorizeAttribute: Attribute
{

}

并且您的授权过滤器只会实现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();
    }
}

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

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;
    }
}

将在您的Application_Start

FilterProviders.Providers.Add(new MyFilterProvider());
于 2013-05-23T08:25:35.273 回答