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.
[…] 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 […]