Asp.net-Mvc

ASP.Net MVC如何判斷一個使用者是否可以訪問一個URL?

  • July 4, 2019

因此,當您有使用者登錄時,我正在閱讀有關登錄循環的另一個問題,設置為返回登錄後他們可能無法訪問的 URL(即管理頁面,並且使用者使用普通帳戶登錄) .

WebForms 下的解決方案似乎是利用該UrlAuthorizationModule.CheckUrlAccessForPrincipal方法。但是,這不適用於使用授權屬性保護的操作方法的 URL。我想我可以找出 URL 指向的方法並對其進行反思以解決我的問題 - 但我似乎無法弄清楚如何從路由表中獲取這些資訊。

有人曾經使用過這個,或者有解決方案嗎?如果我能從一個 URL 中獲取路由資訊,我想我可以解決剩下的問題,但如果有人有一個通用的解決方案 - 即。一些類似於前面提到的用於 MVC 的隱藏方法,那也將非常棒。

我不是在問如何檢查 User 是否有權訪問指定的 Controller/Action pair。我首先需要弄清楚如何根據 URL 從 RouteTable 中獲取 Controller/Action 對。所有背景故事的原因是,如果確實存在UrlAuthorizationModule.CheckUrlAccessForPrincipalMVC 的等價物。

為 MVC 4 更新了 John Farrell (jfar) 的答案(SecurityTrimmingExtensions 類):

public static class SecurityCheck
{
   public static bool ActionIsAuthorized(string actionName, string controllerName)
   {
       IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
       ControllerBase controller = factory.CreateController(HttpContext.Current.Request.RequestContext, controllerName) as ControllerBase;
       var controllerContext = new ControllerContext(HttpContext.Current.Request.RequestContext, controller);
       var controllerDescriptor = new ReflectedControllerDescriptor(controller.GetType());
       var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
       AuthorizationContext authContext = new AuthorizationContext(controllerContext, actionDescriptor);
       foreach (var authAttribute in actionDescriptor.GetFilterAttributes(true).Where(a => a is AuthorizeAttribute).Select(a => a as AuthorizeAttribute))
       {
           authAttribute.OnAuthorization(authContext);
           if (authContext.Result != null)
               return false;
       }
       return true;
   }
}

我從 MvcSitemap 移植並破解了這段程式碼:

public static class SecurityTrimmingExtensions 
{

   /// <summary>
   /// Returns true if a specific controller action exists and
   /// the user has the ability to access it.
   /// </summary>
   /// <param name="htmlHelper"></param>
   /// <param name="actionName"></param>
   /// <param name="controllerName"></param>
   /// <returns></returns>
   public static bool HasActionPermission( this HtmlHelper htmlHelper, string actionName, string controllerName )
   {
       //if the controller name is empty the ASP.NET convention is:
       //"we are linking to a different controller
       ControllerBase controllerToLinkTo = string.IsNullOrEmpty(controllerName) 
                                               ? htmlHelper.ViewContext.Controller
                                               : GetControllerByName(htmlHelper, controllerName);

       var controllerContext = new ControllerContext(htmlHelper.ViewContext.RequestContext, controllerToLinkTo);

       var controllerDescriptor = new ReflectedControllerDescriptor(controllerToLinkTo.GetType());

       var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);

       return ActionIsAuthorized(controllerContext, actionDescriptor);
   }


   private static bool ActionIsAuthorized(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
   {
       if (actionDescriptor == null)
           return false; // action does not exist so say yes - should we authorise this?!

       AuthorizationContext authContext = new AuthorizationContext(controllerContext);

       // run each auth filter until on fails
       // performance could be improved by some caching
       foreach (IAuthorizationFilter authFilter in actionDescriptor.GetFilters().AuthorizationFilters)
       {
           authFilter.OnAuthorization(authContext);

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

       return true;
   }

   private static ControllerBase GetControllerByName(HtmlHelper helper, string controllerName)
   {
       // Instantiate the controller and call Execute
       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;
   }

它可以使用一些記憶體,但對我來說這是一個過早的優化。

引用自:https://stackoverflow.com/questions/2196994