Получение данных модели в AuthorizeAttribute в MVC 3 - PullRequest
7 голосов
/ 27 января 2012

Я украшаю свои действия контроллера с помощью AuthorizeAttribute.

[ServiceAuthorize(Roles="Editor,Publisher,Administrator")]
public JsonResult Create(NewsArticle newsArticle)

В моей модели NewsArticle есть поле, которое я хотел бы использовать в методе OnAuthorize в моем AuthorizeAttribute.

Есть ли какой-нибудь способ получить модель из метода OnAuthorize AuthorizeAttribute?

Я предполагал, что она будет где-то доступна в AuthorizationContext, но я не могу ее найти.Я знаю, что могу получить его в ActionExecutingContext атрибута фильтра, но это означает, что мне потребуется еще один фильтр для моего действия, и я хотел бы иметь возможность выполнить всю авторизацию за один шаг.

Спасибо.

Ответы [ 2 ]

6 голосов
/ 27 января 2012

Есть ли способ получить модель из OnAuthorize? метод AuthorizeAttribute?

Нет, потому что OnAuthorization запускается до подшивки модели. Что вы можете сделать, это прочитать значение из провайдера значений:

public override void OnAuthorization(AuthorizationContext filterContext)
{
    var value = filterContext.Controller.ValueProvider.GetValue("someproperty");
    ...
}
1 голос
/ 08 октября 2014

Я пытался выполнить то же самое, в основном хотел управлять авторизацией с помощью атрибутов параметров метода действия, например:

[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);
}

Это всего лишь подтверждение концепции проекта, над которым я работаю, но похоже, что это работоспособное решение.

...