Zine.net online

Witaj na Zine.net online Zaloguj się | Rejestracja | Pomoc
w Szukaj

Bartek Szafko

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


Tekst ukazał się także na blogu Bartek Szafko
Opublikowane 12 czerwca 2008 20:43 przez bszafko
Attachment(s): ChronSwojeAkcjeMVC.zip

Komentarze:

 

Luke said:

Dzięki! :) Tego było potrzeba do dalszej produkcji mojego bloga :) Dużo googlowałem, ale tego linka akurat nie znalazłem. Przy okazji zauważyłem, że pierwsze linki odnośnie spraw związanych z logowaniem itp. w ASP.NET przedstawiają BARDZO uproszczone podejście i trudno doszukać się w nich naprawdę przydatnych informacji.

czerwca 13, 2008 01:16
 

bszafko said:

a jakbyś nie chciał się bawić w robienie samemu autoryzacji

polecam: http://www.codeplex.com/MvcMembership

czerwca 13, 2008 14:42
 

dario-g said:

czerwca 15, 2008 14:31
Komentarze anonimowe wyłączone
W oparciu o Community Server (Personal Edition), Telligent Systems