asp.net MVC5 - 依赖注入和AuthorizeAttribute

时间:2015-07-29 07:36:33

标签: c# entity-framework dependency-injection asp.net-mvc-5 authorize-attribute

我搜索了很长时间来解决我的问题。我有一个自定义AuthorizeAttribute需要依赖于"服务"有权访问DbContext。 遗憾的是,依赖注入在自定义AuthorizeAttribute中不起作用,并且始终为null。

我想出了一个(对我来说)可接受的解决方案。现在我想知道我的解决方案是否会导致不可预见的行为?

的Global.asax.cs

 CustomAuthorizeAttribute.AuthorizeServiceFactory = () => unityContainer.Resolve<AuthorizeService>();

CustomAuthorizeAttribute.cs

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class CustomAuthorizeAttribute : AuthorizeAttribute
    {
        public static Func<AuthorizeService> AuthorizeServiceFactory { get; set; }

        public Privilege Privilege { get; set; }

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            bool authorized = base.AuthorizeCore(httpContext);
            if (!authorized)
            {
                return false;
            }

            return AuthorizeServiceFactory().AuthorizeCore(httpContext, Privilege);
        }
    }

AuthorizeService.cs

public class AuthorizeService
{
    [Dependency]
    public UserService UserService { private get; set; }

    public bool AuthorizeCore(HttpContextBase httpContext, Privilege privilege)
    {
        ApplicationUser user = UserService.FindByName(httpContext.User.Identity.Name);
        return UserService.UserHasPrivilege(user.Id, privilege.ToString());
    }
}

这是一个可以接受的解决方案吗?我将来会遇到令人讨厌的问题,还是有更好的方法在自定义AuthorizeAttribute中使用依赖注入?

3 个答案:

答案 0 :(得分:14)

  

我有一个需要依赖的自定义AuthorizeAttribute   可以访问DbContext的“服务”。可悲的是依赖   注入在自定义AuthorizeAttribute中不起作用,并且始终如此   空。

IControllerFactory命名空间中的System.Web.Mvc实现会为您的控制器创建Web请求实例。 Controller Factory使用System.Web.Mvc.DependencyResolver来解析每个控制器中的依赖关系。

但是,MVC pipeline中的 ActionFilters / Attributes 不是从Controller Factory创建的,因此使用System.Web.Mvc.DependencyResolver无法解析依赖关系。这就是为什么你的依赖总是null

现在,System.Web.Mvc.DependencyResolverpublicstatic,因此您可以自行访问。

    public class AuthorizeService : AuthorizeAttribute
    {
        private UserService UserService
        {
            get
            {
                return DependencyResolver.Current.GetService<UserService>();
            }
        }

        public bool AuthorizeCore(HttpContextBase httpContext, Privilege privilege)
        {
            ApplicationUser user = UserService.FindByName(httpContext.User.Identity.Name);
            return UserService.UserHasPrivilege(user.Id, privilege.ToString());
        }
    }

假设您的UserService具有 WebRequest 的依赖范围,即其生命周期为每个网络请求一个并且与HttpContext的生命周期相关联如果先前已经解决了一个新的UserService,或者如果这是第一次针对给定的Web请求解析了UserService,则不会构建新的<string-array name="country_names"> <item></item> <item>Denmark</item> </string-array>

答案 1 :(得分:2)

你也可以试试这个:

ASP.NET Web API and dependencies in request scope

public override void OnAuthorization(HttpActionContext filterContext)
{
    var requestScope = filterContext.Request.GetDependencyScope();
    _userService = requestScope.GetService(typeof(IUserService)) as IUserService;
}

//
// Summary:
//     Retrieves the System.Web.Http.Dependencies.IDependencyScope for the given request
//     or null if not available.
//
// Parameters:
//   request:
//     The HTTP request.
//
// Returns:
//     The System.Web.Http.Dependencies.IDependencyScope for the given request or null
//     if not available.
public static IDependencyScope GetDependencyScope(this HttpRequestMessage request);

答案 2 :(得分:2)

在ASP.NET Core中,您可以轻松地请求服务,如下所示:

public class CustomAuthAttribute : AuthorizeAttribute, IAuthorizationFilter
{
    public async void OnAuthorization(AuthorizationFilterContext context)
    {
        // var user = context.HttpContext.User;

        // if (!user.Identity.IsAuthenticated)
        // {
        //     context.Result = new UnauthorizedResult();
        //     return;
        // }

        var userService = context.HttpContext.RequestServices.GetService(typeof(UserService)) as UserService;
    }
}