我搜索了很长时间来解决我的问题。我有一个自定义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中使用依赖注入?
答案 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.DependencyResolver
为public
和static
,因此您可以自行访问。
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;
}
}