我正在尝试查看 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 来解析该方法的任何参数,以便我可以明确地识别正确的参数。有人对如何做到这一点有一些指示吗?或者,框架是否已经提供了解决所需确切方法的方法?
非常感谢!
编辑:更新了方法以包含来自此页面的见解。此最终版本会查看请求的操作方法的
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();
var controller = (ControllerBase)factory.CreateController(
htmlHelper.ViewContext.RequestContext, controllerName);
controllerContext = new ControllerContext(
htmlHelper.ViewContext.RequestContext, controller);
}
var controllerType = controllerContext.Controller.GetType();
var controllerDescriptor = new ReflectedControllerDescriptor(controllerType);
var actionDescriptor = controllerDescriptor.FindAction(
controllerContext, actionName);
if (actionDescriptor == null)
{
return false;
}
var filters = new FilterInfo(
FilterProviders.Providers.GetFilters(controllerContext, actionDescriptor)
);
var authContext = new AuthorizationContext(controllerContext, actionDescriptor);
foreach (IAuthorizationFilter authFilter in filters.AuthorizationFilters)
{
authFilter.OnAuthorization(authContext);
if (authContext.Result != null)
{
return false;
}
}
return true;
}
添加授权码的正常方法是使用授权过滤器。
IAuthorizationFilter.OnAuthorization 提供了一个 AuthorizationContext 对象,该对象具有
ActionDescriptor
属性。