Asp.net mvc 将路由参数传递给自定义属性

Asp.net mvc 将路由参数传递给自定义属性,asp.net-mvc,asp.net-web-api2,Asp.net Mvc,Asp.net Web Api2,我已经创建了一个定制的authorized属性,负责检查用户是否有权访问给定的资源。为了使其通用,我需要将两个变量传递到属性中: public class AuthorizeIsOwnResourceAttribute : AuthorizeAttribute { public ResourcesTypes ResourcesType { get; set; } protected override bool IsAuthorized(System.Web.Http.Contr

我已经创建了一个定制的authorized属性,负责检查用户是否有权访问给定的资源。为了使其通用,我需要将两个变量传递到属性中:

public class AuthorizeIsOwnResourceAttribute : AuthorizeAttribute
{
    public ResourcesTypes ResourcesType { get; set; }

    protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        var httpContext = HttpContext.Current;
        var claimsIdentity = httpContext.User.Identity as ClaimsIdentity;
        var routeData = actionContext.ControllerContext.RequestContext.RouteData;

        switch (ResourcesType)
        {
            case ResourcesTypes.Account:
                return AuthorizeAccount(routeData, claimsIdentity);
        }

        return false;
    }

    private bool AuthorizeAccount(IHttpRouteData routedata, ClaimsIdentity claimsIdentity)
    {

        var id = routedata.Values["id"].ToString();
        var accountClaim = claimsIdentity.Claims.FirstOrDefault(x => x.Type == "Resource-" + ResourcesTypes.Account);
        if (accountClaim == null || accountClaim.Value != id)
        {
            return false;
        }

        return true;
    }
}
  • 请求的资源类型
  • 请求的资源ID
  • 我可以很容易地告诉属性请求了哪种资源类型,但是如何将请求的ID传递到属性中呢?这是我的代码,只缺少最后一个变量(用
    标记):


    有什么建议吗?我想我可以一起删除属性参数,并从
    AuthorizeCore
    中的
    HttpContextBase
    中抽取请求的资源类型和ID;但这是我唯一的选择吗?

    您可以在代码中覆盖AuthorizationContext的ActionDescriptor:

        // Summary:
        //     Initializes a new instance of the System.Web.Mvc.AuthorizationContext class using
        //     the specified controller context and action descriptor.
        //
        // Parameters:
        //   controllerContext:
        //     The context in which the result is executed. The context information includes
        //     the controller, HTTP content, request context, and route data.
        //
        //   actionDescriptor:
        //     An object that provides information about an action method, such as its name,
        //     controller, parameters, attributes, and filters.
        public AuthorizationContext(ControllerContext controllerContext, ActionDescriptor actionDescriptor);
    
    
        // Summary:
        //     Provides information about the action method that is marked by the System.Web.Mvc.AuthorizeAttribute
        //     attribute, such as its name, controller, parameters, attributes, and filters.
        //
        // Returns:
        //     The action descriptor for the action method that is marked by the System.Web.Mvc.AuthorizeAttribute
        //     attribute.
        public virtual ActionDescriptor ActionDescriptor { get; set; }
        //
        // Summary:
        //     Gets or sets the result that is returned by an action method.
        //
        // Returns:
        //     The result that is returned by an action method.
        public ActionResult Result { get; set; }
    

    好的。基于Douglas Gandini的评论,我决定最好的方法可能是让属性决定请求哪个ID。以下是我的工作自定义属性:

    public class AuthorizeIsOwnResourceAttribute : AuthorizeAttribute
    {
        public ResourcesTypes ResourcesType { get; set; }
    
        protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            var httpContext = HttpContext.Current;
            var claimsIdentity = httpContext.User.Identity as ClaimsIdentity;
            var routeData = actionContext.ControllerContext.RequestContext.RouteData;
    
            switch (ResourcesType)
            {
                case ResourcesTypes.Account:
                    return AuthorizeAccount(routeData, claimsIdentity);
            }
    
            return false;
        }
    
        private bool AuthorizeAccount(IHttpRouteData routedata, ClaimsIdentity claimsIdentity)
        {
    
            var id = routedata.Values["id"].ToString();
            var accountClaim = claimsIdentity.Claims.FirstOrDefault(x => x.Type == "Resource-" + ResourcesTypes.Account);
            if (accountClaim == null || accountClaim.Value != id)
            {
                return false;
            }
    
            return true;
        }
    }
    

    简而言之:我从
    actionContext.ControllerContext.RequestContext.RoutedData获取请求的ID直接在我的属性中

    您就有答案了。我认为最好的解决方案是从HttpContextBase访问控制器和操作名称。它更干净,更容易实现,更不容易出错。在仔细考虑这个问题之后,我认为你是绝对正确的。我想我甚至可以从HttpContextBase中提取RoutedData。我将在测试后发布解决方案