7

我试图在 MVC 3 应用程序中查看可能在我的控制器中装饰操作方法的任何身份验证属性。我在自己的 HtmlHelper 扩展方法中执行此操作,这些方法基本上是 ActionLink 的包装器(为您提供我在运行时可用的信息的上下文)。我有一个基本的解决方案,但是重载的方法让它爆炸了。我知道该框架在内部将 url 解析为操作方法,但是在查看 System.Web.Mvc.LinkExtensions 的代码之后,我仍然没有确切地找到这是如何发生的,所以我有点不知道如何来解决这个问题。

这是我迄今为止用于解决相关方法的代码:

private static bool _IsUserAuthorized(HtmlHelper html,
  string controllerName, string actionName)
{
  controllerName = controllerName ??
    html.ViewContext.RouteData.GetRequiredString("controller");

  var factory = ControllerBuilder.Current.GetControllerFactory();
  var controller = factory.CreateController(
    html.ViewContext.RequestContext, controllerName);

  Type controllerType = controller.GetType();
  var methodInfo = controllerType.GetMethod(actionName,
    BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

  ... check authentication
}

所以我目前的问题是,当一个方法被覆盖时,我得到“找到模糊匹配”的异常。我猜我需要处理 RouteValues 来解析方法的任何参数,这样我就可以明确地识别出正确的参数。有没有人有一些关于如何做到这一点的指示?或者,该框架是否已经提供了一种解决所需确切方法的方法?

非常感谢!

4

2 回答 2

2

编辑:更新了方法以包含来自此页面的见解。这个最终版本会查看请求的操作方法的 AuthorizationFilters,并检查用户是否有权执行该操作。

所以我在 System.Web.Mvc.ControllerActionInvoker 中挖掘并找到了我需要的方法和构造函数。ControllerDescriptor.FindAction() 最终成为关键。下面,我复制了我编写的检索所有属性的方法

private static bool _IsUserAuthorized(HtmlHelper htmlHelper,
  string controllerName, string actionName)
{
  ControllerContext controllerContext = null;
  //if controllerName is null or empty, we'll use the 
  // current controller in HtmlHelper.ViewContext.
  if (string.IsNullOrEmpty(controllerName))
  {
    controllerContext = htmlHelper.ViewContext.Controller.ControllerContext;
  }
  else //use the controller factory to get the requested controller
  {
    var factory = ControllerBuilder.Current.GetControllerFactory();
    ControllerBase controller = (ControllerBase)factory.CreateController(
      htmlHelper.ViewContext.RequestContext, controllerName);
    controllerContext = new ControllerContext(
      htmlHelper.ViewContext.RequestContext, controller);
  }

  Type controllerType = controllerContext.Controller.GetType();
  ControllerDescriptor controllerDescriptor = new ReflectedControllerDescriptor(controllerType);
  ActionDescriptor actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
  if (actionDescriptor == null)
    return false;

  FilterInfo filters = new FilterInfo(FilterProviders.Providers.GetFilters(
    controllerContext, actionDescriptor));

  AuthorizationContext authContext = new AuthorizationContext(controllerContext, actionDescriptor);
  foreach (IAuthorizationFilter authFilter in filters.AuthorizationFilters)
  {
    authFilter.OnAuthorization(authContext);
    if (authContext.Result != null)
      return false;
  }
  return true;
}
于 2012-05-01T13:37:30.897 回答
0

添加授权代码的常规方法是使用Authorization Filter

IAuthorizationFilter.OnAuthorization提供了一个具有属性的AuthorizationContext对象。ActionDescriptor

于 2012-04-30T20:59:37.320 回答