Asp.net mvc 3 从MVC 3中的自定义授权属性访问操作方法参数

Asp.net mvc 3 从MVC 3中的自定义授权属性访问操作方法参数,asp.net-mvc-3,security,authorize-attribute,Asp.net Mvc 3,Security,Authorize Attribute,我正在编写一个MVC 3应用程序,用户可以在其中登录并管理他们的数据。我想防止用户查看或篡改其他用户的数据。我的第一反应是在每个动作方法中验证对相关对象的访问,如下所示: public ActionResult ShowDetails(int objectId) { DetailObject detail = _repo.GetById(objectId); if (detail.User.UserID != (Guid)Membership.GetUser().Provider

我正在编写一个MVC 3应用程序,用户可以在其中登录并管理他们的数据。我想防止用户查看或篡改其他用户的数据。我的第一反应是在每个动作方法中验证对相关对象的访问,如下所示:

public ActionResult ShowDetails(int objectId)
{
    DetailObject detail = _repo.GetById(objectId);
    if (detail.User.UserID != (Guid)Membership.GetUser().ProviderUserKey)
    {
        return RedirectToAction("LogOff", "Account");
    }
}
这很好,但我认为最好将对象授权代码放入从AuthorizeAttribute派生的自定义Authorize属性中,然后将其应用于控制器。不幸的是,我无法找到从自定义Authorize属性中访问操作方法参数的方法。相反,我发现访问传入objectId的唯一方法是检查httpContext.Request或filterContext.RequestContext.RoutedData.Values:

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    private int _objectId = 0;
    private IUnitOfWork _unitOfWork;

    public MyAuthorizeAttribute(IUnitOfWork uow)
    {
        _unitOfWork = uow;
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        int.TryParse((string) filterContext.RequestContext.RouteData.Values["id"], out _objectId);
        base.OnAuthorization(filterContext);
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        int objectId = 0;
        if (httpContext.Request.Params.AllKeys.Contains("id", StringComparer.InvariantCultureIgnoreCase))
        {
            int.TryParse(httpContext.Request[idKey], out objectId);
        }

        if (objectId != 0)
        {
            if (!IsAuthorized(objectId, httpContext.User.Identity.Name))
            {
                return false;
            }
        }

        if (_objectId != 0)
        {
            if (!IsAuthorized(objectId, httpContext.User.Identity.Name))
            {
                return false;
            }
        }

        return base.AuthorizeCore(httpContext);
    }

    private bool IsAuthorized(int objectId, string userName)
    {
        DetailObject detail;
        detail = _unitOfWork.ObjectRepository.GetById(objectId);

        if (detail == null)
        {
            return false;
        }

        if (userName != detail.User.UserName)
        {
            return false;
        }

        return true;
    }
}
我发现这种方法非常笨拙。我真的不想在RoutedData中闲逛或请求对象;由于模型绑定已经从RouteData和请求中提取出了相关数据,因此能够访问action方法参数会更干净

我知道我可以从自定义操作筛选器(详细说明)访问操作方法参数,但数据授权代码不应该放在授权筛选器中吗?我看到的授权过滤器示例越多,我就越觉得它们只用于处理角色


我的主要问题是:如何从自定义授权属性访问操作方法参数?

回答您的主要问题:不,很遗憾,
AuthorizationContext
不提供对操作参数的访问

首先,您可以使用
ValueProvider
不必处理id是路由的一部分还是查询参数或HTTP POST,如下所示:

public覆盖权限无效(AuthorizationContext filterContext)
{
字符串id=filterContext.Controller.ValueProvider.GetValue(“id”).AttemptedValue;
...
}
这适用于简单的数据类型,并引入很少的开销。但是,一旦开始为动作参数使用自定义模型绑定,就必须从
ActionFilterAttribute
继承过滤器,以避免双重绑定:

[MyFilter]
公共操作结果MyAction([ModelBinder(typeof(MyModelBinder))]MyModel模型)
{
...
}
公共类MyFilterAttribute:ActionFilterAttribute
{
公共覆盖无效OnActionExecuting(ActionExecutingContext filterContext)
{
var model=filterContext.ActionParameters[“model”]作为MyModel;
...
}
}

虽然出于授权目的从
AuthorizeAttribute
继承语义听起来更好,但没有其他理由这样做。此外,我发现使用
ActionFilterAttribute
更容易,因为您只需覆盖一个方法,而不必为后续方法保留状态。

您找到了解决方案吗?