【问题标题】:How to override the ActionLink behavior如何覆盖 ActionLink 行为
【发布时间】:2013-09-02 23:57:33
【问题描述】:

好的,我想通过 ActionLink 方法为我的网站添加一些安全性。如果用户有足够的权限访问动作/控制器,那么 ActionLink 应该呈现链接。如果不是,它应该返回一个空字符串。现在,ActionLink 是一个静态方法,这使它变得更加困难。有什么方法可以实现我想要做的事情吗?

【问题讨论】:

  • 这不是很好的安全性。如果用户可以弄清楚链接是什么,他们可以直接输入。隐藏链接可能是额外的事情,但您真正的安全应该发生在服务器上。
  • 是的,我做到了,当它全部连接起来时真是太棒了。我会挖掘一些代码...
  • @Matt,如果操作正确,则不正确。您可以创建 ActionLink,在完全呈现链接之前从 class/ 方法查询 Authorize 属性。因此,您可以控制链接的可见性以及对方法的访问权限,只需 Authorize 属性即可。

标签: asp.net-mvc-2 overriding actionlink


【解决方案1】:

新的AuthorizeActionLink 扩展方法。根据需要重载。

public static MvcHtmlString AuthorizeActionLink(this HtmlHelper helper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
{
    if (HasActionPermission(helper, actionName, controllerName))
        return helper.ActionLink(linkText, actionName, controllerName, routeValues, htmlAttributes);

    return MvcHtmlString.Empty;
}

public static MvcHtmlString AuthorizeActionLink(this HtmlHelper helper, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
{
    if (HasActionPermission(helper, actionName, controllerName))
        return helper.ActionLink(linkText, actionName, controllerName, routeValues, htmlAttributes);

    return MvcHtmlString.Empty;
}

在确定用户是否已获得授权方面进行繁琐工作的方法

static bool HasActionPermission(this HtmlHelper htmlHelper, string actionName, string controllerName)
{
    ControllerBase controllerToLinkTo = string.IsNullOrEmpty(controllerName)
        ? htmlHelper.ViewContext.Controller
        : GetControllerByName(htmlHelper, controllerName);

    ControllerContext controllerContext = new ControllerContext(htmlHelper.ViewContext.RequestContext, controllerToLinkTo);
    ReflectedControllerDescriptor controllerDescriptor = new ReflectedControllerDescriptor(controllerToLinkTo.GetType());
    ActionDescriptor actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);

    return ActionIsAuthorized(controllerContext, actionDescriptor);
}

static bool ActionIsAuthorized(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
    if (actionDescriptor == null)
        return false;

    AuthorizationContext authContext = new AuthorizationContext(controllerContext, actionDescriptor);
    foreach (IAuthorizationFilter authFilter in actionDescriptor.GetFilters().AuthorizationFilters)
    {
        authFilter.OnAuthorization(authContext);

        if (authContext.Result != null)
            return false;
    }

    return true;
}

static ControllerBase GetControllerByName(HtmlHelper helper, string controllerName)
{
    IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();

    IController controller = factory.CreateController(helper.ViewContext.RequestContext, controllerName);

    if (controller == null)
    {
        throw new InvalidOperationException(
            string.Format(
                CultureInfo.CurrentUICulture,
                "Controller factory {0} controller {1} returned null",
                factory.GetType(),
                controllerName));
    }

    return (ControllerBase)controller;
}

【讨论】:

  • 所以没有办法用相同的 Html.ActionLink() 方法做到这一点?
  • 不,但我认为这是在整个应用程序中显示此类条件链接的一种很好的可重用方式
  • @hunter 如果我们在页面上列出了 15 个用户的用户的编辑链接,则整个代码将执行 15 次。仅在控制器中计算 haspermission 值并通过某些视图模型将其推送到视图上不是更好吗
  • @Muhammad 对于任何给定的动作/控制器组合,没有理由不能通过在HttpContext.Items 中添加HasActionPermission 的结果来扩展它。这实际上是个好主意。
  • @hunter 你能给我一个起点吗,我的意思是如何接近它
猜你喜欢
  • 2020-05-21
  • 2017-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多