2011-03-29 9 views
5

Ok, quiero agregar algo de seguridad a mi sitio a través del método ActionLink. Si el usuario tiene suficientes derechos para acceder a la acción/controlador, entonces ActionLink debería representar el enlace. Si no, debería devolver una cadena vacía. Ahora, el ActionLink es un método estático y eso lo hace todo más difícil. ¿Hay alguna manera de lograr lo que estoy tratando de hacer?Cómo anular el comportamiento de ActionLink

+0

Eso no es muy buena seguridad. Si el usuario puede descubrir qué es el enlace, puede ingresarlo directamente. Ocultar el enlace puede ser algo más que hacer, pero su seguridad real debería tener lugar en el servidor. –

+0

Sí, lo hice, es increíble cuando todo está conectado. Desenterraré algún código ... – hunter

+2

@Matt, no es cierto si se hace correctamente. Puede crear ActionLinks que consulten el atributo 'Authorize' de la clase/método antes de representar el enlace. De modo que puede controlar la visibilidad del enlace y acceder al método con nada más que el atributo Autorizar. – hunter

Respuesta

8

nuevo AuthorizeActionLink método de extensión. Sobrecarga según sea necesario.

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; 
} 

métodos que hacen el trabajo sucio en averiguar si el usuario está autorizado

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; 
} 
+0

entonces no hay forma de hacerlo con el mismo método Html.ActionLink()? –

+0

no, pero creo que esta es una gran forma reutilizable para hacer este tipo de visualización de enlace condicional en toda su aplicación – hunter

+0

bien, entonces :) gracias –

Cuestiones relacionadas