2011-03-29 4 views
5

좋아, ActionLink 메서드를 통해 내 사이트에 보안을 추가하고 싶습니다. 사용자가 액션/컨트롤러에 접근 할 수있는 충분한 권한을 가지고 있다면 ActionLink는 링크를 렌더링해야합니다. 그렇지 않으면 빈 문자열을 반환해야합니다. 이제는 ActionLink가 정적 메서드이므로 모든 작업을 더 어렵게 만듭니다. 내가 무엇을하려고하는지 달성 할 수있는 방법이 있습니까?ActionLink 동작을 재정의하는 방법

+0

공인되어 있는지 파악에 더러운 일을

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

방법. 사용자가 링크가 무엇인지 파악할 수 있다면 링크를 직접 입력 할 수 있습니다. 링크를 숨기는 것은 할 수있는 일이지만 실제 보안은 서버에서 이루어져야합니다. –

+0

그래, 내가 그랬어, 모두 유선 때 굉장해. 일부 코드를 파헤칩니다. – hunter

+2

@Matt 제대로 완료되면 true가 아닙니다. 링크를 렌더링하기 전에 클래스/메소드에서'Authorize' 속성을 쿼리하는 ActionLink를 생성 할 수 있습니다. 따라서 Authorize 속성 이상으로 메소드의 링크 및 액세스에 대한 가시성을 제어 할 수 있습니다. – hunter

답변

8

신규 AuthorizeActionLink 확장 방법. 필요에 따라 과부하. 사용자가 아주 좋은 보안되지 즉

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

그래서 동일한 Html.ActionLink() 메소드로 수행 할 방법이 없습니까? –

+0

아니요,하지만 이것은 전체 응용 프로그램에 걸쳐 이러한 유형의 조건부 링크 표시를 수행하는 훌륭한 재사용 가능한 방법이라고 생각합니다. – hunter

+0

다음에 감사합니다. –

관련 문제