Ukrywanie linków dla nieautoryzowanych użytkowników

3

Ostatnio pokazałem jak dobrać się do typu kontrolera dla dowolnego żądania. Było mi to potrzebne do wykonania zadania, które okazało się dużo bardziej skomplikowane niż początkowo zakładałem.

Chciałem mianowicie być w stanie zrobić takie coś:

  1:  <% if (MVC.Administration.Users.DisableUser().IsUserAuthorized(this.ViewContext.RequestContext)) { %>
  2:      <a href="#" data-role="disable-user">Disable user</a>
  3:  <% } %>

Czyli: w dowolnym miejscu (w tym przypadku – w widoku) sprawdzić, czy aktualny użytkownik ma uprawnienia do wykonania akcji pod danym URLem (ta fajna, silnie typowana notacja dzięki T4MVC). Bo po co go wyświetlać skoro i tak nie może go użyć? (można to oczywiście zamknąć w jakimś helperze)

Kod metody IsUserAuthorized przedstawia się następująco:

  1:  public static class ActionResultExtensions
  2:  {
  3:      public static bool IsUserAuthorized(this ActionResult @this, RequestContext requestContext)
  4:      {
  5:          string controllerName = (string)@this.GetRouteValueDictionary()["Controller"];
  6:          string actionName = (string)@this.GetRouteValueDictionary()["Action"];
  7:  
  8:          Type controllerType = ControllerTypeLocator.FindControllerType(
  9:              requestContext, controllerName
 10:          );
 11:  
 12:          var controllerDescriptor = new ReflectedControllerDescriptor(controllerType);
 13:  
 14:          var controllerLevelAuthorization = controllerDescriptor
 15:              .GetCustomAttributes(true).OfType<AuthorizeAttribute>();
 16:  
 17:          var actionsDescriptors = controllerDescriptor.GetCanonicalActions
 18:              ().Where(x => x.ActionName == actionName);
 19:  
 20:          var actionLevelAuthorization = actionsDescriptors
 21:              .SelectMany(x => x.GetCustomAttributes(true).OfType<AuthorizeAttribute>());
 22:  
 23:          bool isAuthorized = controllerLevelAuthorization.Concat(actionLevelAuthorization)
 24:              .Select(x => new OpenAuthorizeAttribute(x))
 25:              .All(x => x.Authorized(requestContext));
 26:  
 27:          return isAuthorized;
 28:      }
 29:  }

Wykorzystany wyżej OpenAuthorizeAttribute pochodzi z projektu MvcContrib. A ControllerTypeLocator przedstawiłem poprzednim poście.

No i na koniec wspomniany helper generujący linki dla autoryzowanych użytkowników:

  1:  public static MvcHtmlString ActionLinkIfAuthorized(this HtmlHelper @this, string linkText, ActionResult actionResult, string format, object linkAttributes)
  2:  {
  3:      if (actionResult.IsUserAuthorized(@this.ViewContext.RequestContext) == false)
  4:      {
  5:          return MvcHtmlString.Empty;
  6:      }
  7:  
  8:      var a = @this.ActionLink(linkText, actionResult, linkAttributes);
  9:  
 10:      if (format.HasNoText())
 11:      {
 12:          return a;
 13:      }
 14:  
 15:      return MvcHtmlString.Create(format.FormatWith(a.ToString()));
 16:  }
Share.

About Author

Programista, trener, prelegent, pasjonat, blogger. Autor podcasta programistycznego: DevTalk.pl. Jeden z liderów Białostockiej Grupy .NET i współorganizator konferencji Programistok. Od 2008 Microsoft MVP w kategorii .NET. Więcej informacji znajdziesz na stronie O autorze. Napisz do mnie ze strony Kontakt. Dodatkowo: Twitter, Facebook, YouTube.

3 Comments