Как переопределить поведение ActionLink - PullRequest
5 голосов
/ 29 марта 2011

Хорошо, я хочу повысить безопасность своего сайта с помощью метода ActionLink. Если у пользователя достаточно прав для доступа к действию / контроллеру, тогда ActionLink должен отобразить ссылку. Если нет, он должен вернуть пустую строку. Теперь ActionLink является статическим методом, и это делает его все более сложным. Есть ли способ добиться того, что я пытаюсь сделать?

1 Ответ

8 голосов
/ 29 марта 2011

новый 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;
}
...