Chroń swoje akcje w MVC

Bynajmniej nie będzie w tym poście o rynkach kapitałowych 😉

Jeden z czytelników niedawno zapytał mnie w jaki sposób chronić akcję przed niepowołanym dostępem.Okazauje się, że ASP .NET MVC z pomocą standardowych komponentów .NET stosunkowo to zrealizować.

WyobraĽmy sobie, że mamy akcję, którą chcielibyśmy chronić, tak żeby tylko użytkownik o nazwie Administrator mógł ją wywołać:

    1 public ActionResult About()

    2 {

    3     ViewData[“Title”] = “About Page”;

    4 

    5     return View();

    6 }

(używam już składni z preview 3)

W standardowym .NET istnieje atrybut pozwalający ograniczać dostęp do metod nazywa się PrincipalPermission ( dużo o nim można przeczytać na msdnie). Pozwala on określić, czy żeby uzyskać dostęp, wystarczy być tylko zalogowanym, czy trzeba należeć do określonej roli, czy może mieć konkretną nazwę użytkownika. W wypadku, gdy ktoś niepowołany uzyska dostęp do metody zrzucony zostanie wyjątek SecurityException.

Jednak, takie zachowanie(rzucanie wyjątkami) nie jest porządanym zachowaniem dla naszej aplikacji w MVC, trzeba by przekierować użytkownika na przykład na stronę logowania. W MVC istnieje pojęcie filtrów( dziedziczących po ActionFilterAttribute), które pozwalają przechwytywać wykonywanie akcji i realizować określone zadania, przykładowy filtr mógłby wyglądać tak(tylko najważniejszy kod, reszta do ściągnięcia):

    1 public override void OnActionExecuted(ActionExecutedContext filterContext)

    2  {

    3     Exception exception = filterContext.Exception;

    4 

    5     if (exception == null)

    6         return;

    7 

    8     foreach (Type exceptionType in ExceptionTypes)

    9     {

   10         if (exceptionType.IsAssignableFrom((exception.InnerException ?? exception).GetType()))

   11         {

   12             filterContext.ExceptionHandled = true;

   13 

   14             if (Redirect)

   15             {

   16                 RouteValueDictionary routes = new RouteValueDictionary();

   17                 routes.Add(“Action”, Action);

   18                 routes.Add(“Controller”, Controller);                     

   19                 filterContext.Result = new RedirectToRouteResult(routes);

   20             }

   21             else

   22             {

   23                 filterContext.HttpContext.Response.Clear();

   24 

   25                 filterContext.HttpContext.Response.StatusCode = ResponseCode;

   26                 filterContext.HttpContext.Response.StatusDescription = ResponseDescription;

   27 

   28                 filterContext.HttpContext.Response.ContentType = “text/html”;

   29                 filterContext.HttpContext.Response.Write(“<html><head><title>” + ResponseDescription + “</title></head><body>”);

   30                 filterContext.HttpContext.Response.Write(“<h2>” + ResponseDescription + “</h2>”);

   31                 filterContext.HttpContext.Response.Write(“<p>” + (exception.InnerException ?? exception).Message + “</p>”);

   32                 filterContext.HttpContext.Response.Write(“</body></html>”);

   33                 filterContext.HttpContext.Response.Flush();

   34 

   35                 filterContext.HttpContext.ApplicationInstance.CompleteRequest();

   36             }

   37         }

   38     }

   39  }

( przykład zapożyczony z biblioteki ManagedFusion – spodobało mi się to podejście)

Teraz wystarczy przerobić naszą akcję, aby wyglądała tak:

    1 [PrincipalPermission(SecurityAction.Demand, Name = “Administrator”)]

    2 [ExceptionHandler(“Login”, “Uzytkownik”, typeof(SecurityException))]

    3 public ActionResult About()

    4 {

    5     ViewData[“Title”] = “About Page”;

    6 

    7     return View();

    8 }

Spowoduje to, przekierowanie użytkownika do akcji Login w kontrolerze Uzytkownik.

Oczywiście należy zatroszczyć się, aby do aplikacji można było się zalogować – można w tym celu użyć normalnej autentykacji forms albo dowolnej innej obsługiwanej w asp .net. Standardowe MembershipProvidery i RoleProvidery też dadzą się użyć.

Do ściągnięcia jest kod przykładowej aplikacji z autoryzacją Forms, nie jest on w żadnym wypadku produkcyjny, a jego napisanie zajęło mi tylko 20 minut.

Polecam także świetny artykuł Roba Connery na ten temat

One thought on “Chroń swoje akcje w MVC

  1. […] and filters were implemented in MVC I used a PrincipalPermission attribute (more on this in blog post only in polish). PrincipalPermission is a standard System.Security mechanism to limit access to […]

Comments are closed.