我正在使用AuthorizeAttribute装饰我的控制器操作。
[ServiceAuthorize(Roles="Editor,Publisher,Administrator")]
public JsonResult Create(NewsArticle newsArticle)
我的NewsArticle模型中有一个字段,我想在AuthorizeAttribute中的OnAuthorize方法中使用。
有没有办法从AuthorizeAttribute的OnAuthorize方法中获取模型?
我认为它可以在AuthorizationContext中的某个地方使用但我找不到它。我知道我可以在过滤器属性的ActionExecutingContext中找到它,但这意味着我需要在我的操作上使用另一个过滤器,我希望能够在一个步骤中执行所有授权。
感谢。
答案 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);
}
这只是我正在进行的项目的概念验证,但它似乎是一个可行的解决方案。