Я пытался выполнить то же самое, в основном хотел управлять авторизацией с помощью атрибутов параметров метода действия, например:
[MyAuthorize]
public ActionResult MyAction(
[Require(Permission.Write)] MyCustomObject arg1,
[Require(Permission.Read)] MyCustomObject arg2
) {
// ... all authorization would be handled before the action is invoked ...
}
class MyAuthorize : AuthorizeAttribute {
public override void OnAuthorization(AuthorizationContext filterContext) {
// ... filterContext doesn't have the argument objects ...
}
}
Я столкнулся с той же проблемой при переопределении AuthorzeAttribute.OnAuthorization(...)
связанные с моделью аргументы еще не существуют.Чтобы выполнить то, что мне было нужно, я реализовал IActionFilter
, который предоставляет метод OnActionExecuting
, который будет вызываться после привязки модели, но до вызова действия.Моя прототипная реализация выглядит следующим образом:
class MyAuthorizeAttribute : AuthorizeAttribute, IActionFilter {
public override void OnAuthorization(AuthorizationContext filterContext) {
// ... I guesss this isn't really needed any more.
// the auth check is handled in OnActionExecuting.
}
void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext) {
}
void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext) {
foreach (var param in filterContext.ActionDescriptor.GetParameters()) {
var attr = (RequireAttribute)param.GetCustomAttributes(typeof(RequireAttribute), false).FirstOrDefault();
if(attr != null) {
Object obj;
if (filterContext.ActionParameters.TryGetValue(param.ParameterName, out obj)) {
var sec = obj as ISecurable;
if (sec == null || !sec.HasPermission(filterContext.RequestContext, attr.Permission)) {
filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.Unauthorized);
}
}
}
}
}
}
interface ISecurable {
bool HasPermission(Permission permission);
}
Это всего лишь подтверждение концепции проекта, над которым я работаю, но похоже, что это работоспособное решение.