7

我正在使用 ASP.NET Web API,我需要获得授权,所以我创建了自定义授权属性

public class CustomAuthorizationAttribute : AuthorizeAttribute

为了在构造函数中注入依赖项,我有以下内容:

        public CustomAuthorizationAttribute(IAccountBL accountBl)
    {
        _accountBL = accountBl;
    }

IAccountBL我有与数据库交互的方法,检查用户是否被授权发出请求。在成员 API 控制器中,我已经注册了该属性

    [CustomAuthorization]
public class MemberController : ApiController

但我收到以下错误

Project.Account.AccountBL' 不包含采用 0 个参数的构造函数

如果我像这样注册它

[CustomAuthorization(IAccountBL)]

在此处输入图像描述

谢谢

4

4 回答 4

12

动作过滤器只是属性。您无法控制 CLR 何时实例化这些属性。一种可能性是编写标记属性:

public class CustomAuthorizationAttribute : Attribute { }

然后是实际的动作过滤器:

public class CustomAuthorizationFilter : ActionFilterAttribute
{
    private readonly IAccountBL accountBL;
    public CustomAuthorizationFilter(IAccountBL accountBL)
    {
        this.accountBL = accountBL;
    }

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<CustomAuthorizationAttribute>().Any() || 
            actionContext.ActionDescriptor.GetCustomAttributes<CustomAuthorizationAttribute>().Any())
        {
            // here you know that the controller or action is decorated 
            // with the marker attribute so that you could put your code
        }
    }
}

最后将其注册为全局操作过滤器:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        ...

        IAccountBL accountBL = ...
        config.Filters.Add(new CustomAuthorizationFilter(accountBL));
    }
}

最后你可以使用标记属性:

[CustomAuthorization]
public class MemberController : ApiController
{
    ...
}
于 2013-08-23T15:49:37.120 回答
8

您可以使用GetDependencyScope类的扩展方法在过滤器中获取依赖项HttpRequestMessage。这不是依赖注入的规范方式,但可以用作解决方法。一个基本示例可能如下所示:

    public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
    {
        var dependencyScope = context.Request.GetDependencyScope();
        var dependency = dependencyScope.GetService(typeof (MyDependencyType));
        //use your dependency here
    }

此方法可与构造函数注入一起使用以简化单元测试:

public class MyAuthenticationFilter : Attribute, IAuthenticationFilter
{
    private Func<HttpRequestMessage, MyDependencyType> _dependencyFactory;

    public MyAuthenticationFilter() :
        this(request => (MyDependencyType)request.GetDependencyScope().GetService(typeof(MyDependencyType)))
    {
    }

    public MyAuthenticationFilter(Func<HttpRequestMessage, MyDependencyType> dependencyFactory)
    {
        _dependencyFactory = dependencyFactory;
    }

    public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
    {
        var dependencyScope = context.Request.GetDependencyScope();
        var dependency = dependencyFactory.Invoke(context.Request);
        //use your dependency here
    }

    public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
    {
        throw new NotImplementedException();
    }

    public bool AllowMultiple { get; private set; }
}
于 2015-10-17T10:27:09.053 回答
2

如果有人发现类似的问题,这就是我设法解决的方法。

我的自定义过滤器继承了IAutofacAuthorizationFilter. 除了这个,你还可以继承IAutofacExceptionFilterand IAutofacActionFilter。在我的 DI 容器中,我为每个我想像这样使用的控制器注册了这个过滤器

        builder.Register(c => new CustomAuthorizationAttribute(c.Resolve<IAccountBL>()))
               .AsWebApiAuthorizationFilterFor<MemberController>()
               .InstancePerApiRequest();
于 2013-08-26T12:21:38.367 回答
0

如果您使用任何容器在应用程序上注册了您的服务,那么很容易从范围内的任何位置获取您的服务实例。只需按照以下代码获取您的服务。

var myService = DependencyResolver.Current.GetService(typeof(IMyService)) as IMyService;

请确保您已包含System.Web.Mvc在文件中。

编码快乐!!!

于 2020-01-10T16:20:08.653 回答