Tôi có một tình huống mà tôi cần phải tiêm một số phụ thuộc vào bộ lọc hành động, cụ thể là nhà cung cấp ủy quyền tùy chỉnh của tôi trong thuộc tính ủy quyền tùy chỉnh của tôi. Tôi tình cờ gặp rất nhiều người và các bài đăng đang nói rằng chúng ta nên tách 'siêu dữ liệu thuộc tính' khỏi 'hành vi'. Điều này có ý nghĩa và cũng có một thực tế là các thuộc tính lọc không được khởi tạo thông qua 'DependencyResolver' do đó rất khó để chèn các phụ thuộc.IFilterProvider và tách mối quan tâm
Vì vậy, tôi đã làm một chút refactoring mã của tôi và tôi muốn biết nếu tôi đã có nó đúng (Tôi đang sử dụng Castle Windsor như khuôn khổ DI).
Trước hết tôi lột thuộc tính của tôi để chỉ chứa các dữ liệu thô Tôi cần
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyAuthorizeAttribute : Attribute
{
public string Code { get; set; }
}
Tôi tạo ra một bộ lọc cho phép tùy chỉnh mà sẽ chứa logic của việc xác định nếu người dùng hiện có sự uỷ quyền thích hợp
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;
}
}
Phần cuối cùng là tạo nhà cung cấp bộ lọc tùy chỉnh sẽ tìm nạp thuộc tính cụ thể này và khởi tạo bộ lọc tùy chỉnh của tôi chuyển phụ thuộc của nó và bất kỳ dữ liệu nào cần, trích xuất từ thuộc tính.
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);
}
}
}
Bước cuối cùng là đăng ký nhà cung cấp bộ lọc trong global.asax
FilterProviders.Providers.Add(new MyAuthorizationFilterProvider(_container));
Vì vậy, tôi tự hỏi đầu tiên, nếu tôi đã có ý tưởng đúng đắn và thứ hai, những gì có thể được cải thiện.
Xin chào Francois, tôi đã đưa ra một giải pháp khá giống với cùng một vấn đề với bạn. Tôi hiện đang tự hỏi mình những câu hỏi tương tự như bạn. Bạn đã kết thúc bằng cách sử dụng giải pháp này? Bất kỳ vấn đề với nó theo thời gian? Bạn có đề nghị nào không? Cảm ơn bạn. –