在MVC 3的AuthorizeAttribute中获取模型数据

时间:2012-01-26 22:29:34

标签: asp.net-mvc-3 action-filter

我正在使用AuthorizeAttribute装饰我的控制器操作。

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

我的NewsArticle模型中有一个字段,我想在AuthorizeAttribute中的OnAuthorize方法中使用。

有没有办法从AuthorizeAttribute的OnAuthorize方法中获取模型?

我认为它可以在AuthorizationContext中的某个地方使用但我找不到它。我知道我可以在过滤器属性的ActionExecutingContext中找到它,但这意味着我需要在我的操作上使用另一个过滤器,我希望能够在一个步骤中执行所有授权。

感谢。

2 个答案:

答案 0 :(得分:6)

  

有没有办法从OnAuthorize中获取模型   AuthorizeAttribute的方法?

否,因为OnAuthorization在模型绑定器之前运行。你可以做的是从值提供者中读取值:

public override void OnAuthorization(AuthorizationContext filterContext)
{
    var value = filterContext.Controller.ValueProvider.GetValue("someproperty");
    ...
}

答案 1 :(得分:1)

我试图完成同样的事情,基本上想要用动作方法参数的属性来控制授权,例如:

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

这只是我正在进行的项目的概念验证,但它似乎是一个可行的解决方案。