我有一種情況,我需要在操作篩選器中注入一些依賴項,即我的自定義授權屬性中的自定義授權提供程序。我偶然發現很多人和帖子都在說我們應該把'屬性元數據'和'行爲'區分開來。這是有道理的,並且還有一個事實,即filter屬性沒有通過'DependencyResolver'實例化,所以很難注入依賴關係。IFilterProvider和問題分離
因此,我對代碼做了一些重構,並且想知道我是否正確(我使用Castle Windsor作爲DI框架)。
首先,我剝我的屬性只包含原始數據,我需要
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyAuthorizeAttribute : Attribute
{
public string Code { get; set; }
}
我創建了一個自定義授權過濾器,將包含確定當前用戶是否具有正確的授權
public class MyAuthorizationFilter : IAuthorizationFilter
{
private IAuthorizationProvider _authorizationProvider;
private string _code;
public MyAuthorizationFilter(IAuthorizationProvider authorizationProvider, string code)
{
Contract.Requires(authorizationProvider != null);
Contract.Requires(!string.IsNullOrWhiteSpace(code));
_authorizationProvider = authorizationProvider;
_code = code;
}
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (filterContext.HttpContext.Request.IsAuthenticated)
{
BaseController controller = filterContext.Controller as BaseController;
if (controller != null)
{
if (!IsAuthorized(controller.CurrentUser, controller.GetCurrentSecurityContext()))
{
// forbidden
filterContext.RequestContext.HttpContext.Response.StatusCode = 403;
if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.Result = new RedirectToRouteResult("default", new RouteValueDictionary(new
{
action = "http403",
controller = "error"
}), false);
}
else
{
filterContext.Result = controller.InvokeHttp404(filterContext.HttpContext);
}
}
}
else
{
}
}
else
{
filterContext.Result = new RedirectResult(FormsAuthentication.LoginUrl);
}
}
private bool IsAuthorized(MyUser user, BaseSecurityContext securityContext)
{
bool has = false;
if (_authorizationProvider != null && !string.IsNullOrWhiteSpace(_code))
{
if (user != null)
{
if (securityContext != null)
{
has = _authorizationProvider.HasPermission(user, _code, securityContext);
}
}
}
else
{
has = true;
}
return has;
}
}
的邏輯
最後一部分是創建一個自定義過濾器提供程序,該提供程序將獲取此特定屬性並實例化我的自定義過濾器,以傳遞它的依賴項以及所需的任何數據,從屬性中提取。
public class MyAuthorizationFilterProvider : IFilterProvider
{
private IWindsorContainer _container;
public MyAuthorizationFilterProvider(IWindsorContainer container)
{
Contract.Requires(container != null);
_container = container;
}
public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
Type controllerType = controllerContext.Controller.GetType();
var authorizationProvider = _container.Resolve<IAuthorizationProvider>();
foreach (MyAuthorizeAttribute attribute in controllerType.GetCustomAttributes(typeof(MyAuthorizeAttribute), false))
{
yield return new Filter(new MyAuthorizationFilter(authorizationProvider, attribute.Code), FilterScope.Controller, 0);
}
foreach (MyAuthorizeAttribute attribute in actionDescriptor.GetCustomAttributes(typeof(MyAuthorizeAttribute), false))
{
yield return new Filter(new MyAuthorizationFilter(authorizationProvider, attribute.Code), FilterScope.Action, 0);
}
}
}
的最後一步是在Global.asax
FilterProviders.Providers.Add(new MyAuthorizationFilterProvider(_container));
所以我想先註冊過濾器供應商,如果我有這個想法的權利;第二,什麼可以改善。
嗨,弗朗索瓦,我想出了一個非常類似的解決方案,爲你解決同樣的問題。我現在正在問自己和你一樣的問題。你最終使用這個解決方案嗎?隨着時間的推移它的任何問題?你有什麼建議嗎?謝謝。 –