在ASP.NET MVC3中使用操作参数的自定义授权属性

23

我有一个控制器,只有在加载特定参数时才需要请求授权。比如当参数ID为8时。

我想出了使用自定义验证属性的方法,代码如下:

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (/* Action's inputparameter ID = 8 */)
        {
        return base.AuthorizeCore(httpContext);
        }
        return true;
    }
}

我的动作看起来像这样(并不是很有趣)

[MyAuthorize]
public ActionResult Protected(int id)
{
    /* custom logic for setting the viewmodel from the id parameter */
    return View(viewmodel);
}

问题就像你所看到的一样,我不知道如何在授权属性中检查那个ID参数。你能帮我想一个解决方案吗?

4个回答

33
如果id作为请求参数(GET或POST)或路由数据参数传递:
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
    // first look at routedata then at request parameter:
    var id = (httpContext.Request.RequestContext.RouteData.Values["id"] as string) 
             ??
             (httpContext.Request["id"] as string);
    if (id == "8")
    {
        return base.AuthorizeCore(httpContext);
    }
    return true;
}

代码是冗余的,请查看下面我的解决方案。 - Herman Kan
@Darin,您能告诉我如果操作的输入参数是一个模型对象,怎么样检索该模型对象而不是命名参数吗? - qurban
听起来你实际上正在寻找的是https://dev59.com/DXM_5IYBdhLWcg3wiDyA - Worthy7

10
只要AuthorizeAttribute被继承,您就可以从AuthorizationContext获取参数,方法如下:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        string idParam = filterContext.Controller.ValueProvider.GetValue("id").AttemptedValue;
        int id;

        if (int.TryParse(idParam, out id))
        {
            if (id == 8) // apply your business logic here
                return;
        }

        filterContext.Result = new HttpUnauthorizedResult();
    }
}

[MyAuthorize]
public ActionResult Protected(int id)
{
    return View();
}

ValueProvider会遍历所有已注册的提供程序,其中默认包括RouteDataValueProviderQueryStringValueProviderFormValueProvider,并为您完成所有工作。

否则,我建议使用ActionFilterAttribute


这并没有完全回答我的问题。我想根据id参数的值启用/禁用授权。有没有办法从OnAuthorization处理程序影响授权?您能详细说明一下您回答中的...部分吗? - vinczemarton
@SoonDead,我改了我的例子。你可以看到,它仍然非常简单,但完全可用。 - Herman Kan

2
你需要类似于这样的东西。
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        int? id = GetId(filterContext);

        if (id.HasValue)
        {
          ...
        }
    }

    private static int? GetId(ActionExecutingContext filterContext)
    {
        int? Id = null;

        if (filterContext.ActionParameters.ContainsKey("Id"))
        {
            Id = (int?)filterContext.ActionParameters["Id"];
        }
    }

1
是的,有点类似,但是在AuthorizeCore方法中我有一个HttpContextBase参数,而不是一个ActionExecutingContext。而且我不知道如何在OnActionExecuting方法中编写授权逻辑。 - vinczemarton
2
这是一篇很棒的文章,解释了如何访问ActionParameters以进行授权目的:http://www.joe-stevens.com/2010/08/19/asp-net-mvc-authorize-attribute-using-action-parameters-with-the-actionfilterattribute/ - Michael La Voie

1
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var rd = httpContext.Request.RequestContext.RouteData;
        string currentAction = rd.GetRequiredString("action");
        string actionparam =Convert.ToString(rd.Values["param"]);

        if (id == actionparam)
        {
            return base.AuthorizeCore(httpContext);
        }
return true;
 }

这与Darin Dimitrov的答案有何不同? - vinczemarton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接