Jak możemy ustawić autoryzację dla całego obszaru w ASP.NET MVC?
Mam obszar administratora i chcę, aby tylko administratorzy weszli w ten obszar. Rozważałem dodanie autoryzowanego atrybutu do każdego kontrolera w obszarze administracyjnym. Czy nie ma eleganckiego rozwiązania, czy tej funkcji nie ma w samym frameworku?
Edytuj: Przepraszam, powinienem był wcześniej o tym wspomnieć. Używam niestandardowego AuthorizedAttribute wywodzącego się z AuthorizeAttribute.
6 answers
Www.zabezpieczenia oparte na konfiguracji powinny prawie nigdy być używane w aplikacji MVC. Powodem tego jest to, że wiele adresów URL może potencjalnie trafić w kontroler i umieścić te kontrole w sieci.config Pamiętaj-Kontrolery nie są powiązane z obszarami, trasy są powiązane z obszarami. Fabryka kontrolerów MVC będzie z przyjemnością obsługiwać Kontrolery z folderu obszary / dla żądań innych niż obszary, jeśli nie będzie konfliktu.
Na przykład, używając domyślna struktura projektu, dodając obszar administracyjny z kontrolerem AdminDefaultController, możesz nacisnąć ten kontroler przez /Admin/AdminDefault /Index i/AdminDefault / Index.
Jedynym obsługiwanym rozwiązaniem jest umieszczenie atrybutu na klasie bazowej kontrolera i upewnienie się, że każdy kontroler w obszarze podklasa tę klasę bazową.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-23 17:47:27
Właśnie badałem ten sam problem. Ponieważ zabezpieczenie kontrolerów w oparciu o obszary nie jest możliwe , przychodzi na myśl prostsza opcja.
Utwórz definicję kontrolera bazowego dla każdego obszaru, który nadpisuje kontroler i dodaj do tego wymagane zabezpieczenia. Następnie musisz tylko upewnić się, że każdy kontroler w obszarze nadpisuje AreaController zamiast kontrolera. Na przykład:
/// <summary>
/// Base controller for all Admin area
/// </summary>
[Authorize(Roles = "Admin")]
public abstract class AdminController : Controller { }
Nadal wymaga, aby każdy kontroler w obszarze administracyjnym był pobierany z ta baza,
public class HomeController : AdminController
{
// .. actions
}
Ale przynajmniej masz jeden punkt, w którym definiujesz bezpieczeństwo obszaru.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-25 08:34:01
Jeśli cały Twój kod administracyjny znajduje się w jednym kontrolerze, dodaj Authorize do całej klasy.
[Authorize]
public class AdminController : Controller
{
.......
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-23 15:17:12
Dopiero zacząłem... ale jak na razie to działa całkiem dobrze dla mnie.
Tworzę własną klasę AuthorizeAttribute i dodaję ją do funkcji RegisterGlobalFilters.
W Customautorizeattribute sprawdzam różne warunki w zależności od obszaru, w którym się znajduje.
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new CustomAuthorizeAttribute());
filters.Add(new HandleErrorAttribute());
}
}
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var routeData = httpContext.Request.RequestContext.RouteData;
var controller = routeData.GetRequiredString("controller");
var action = routeData.GetRequiredString("action");
var area = routeData.DataTokens["area"];
var user = httpContext.User;
if (area != null && area.ToString() == "Customer")
{
if (!user.Identity.IsAuthenticated)
return false;
}
else if (area != null && area.ToString() == "Admin")
{
if (!user.Identity.IsAuthenticated)
return false;
if (!user.IsInRole("Admin"))
return false;
}
return true;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-11 01:16:40
Aktualnie akceptowana odpowiedź nie jest najbezpieczniejszym rozwiązaniem, ponieważ wymaga od programisty zawsze pamiętania o dziedziczeniu nowej klasy bazowej dla nowych kontrolerów lub akcji ("Czarna lista"; pozwalająca użytkownikom na dostęp do wszystkiego, chyba że akcja jest ręcznie ograniczona). Powoduje to szczególnie problemy, gdy nowi programiści, nie znający Twoich rytuałów, są wprowadzani do projektu. Łatwo jest zapomnieć o dziedziczeniu odpowiedniej klasy kontrolera, jeśli jest to zrobione w ten sposób, zwłaszcza po oderwaniu wzroku od projektu na tygodnie, miesiące lub lata. Jeśli programista zapomni dziedziczyć, nie jest oczywiste, że w projekcie występuje luka w zabezpieczeniach.
Bezpieczniejszym rozwiązaniem tego problemu jest odmowa dostępu do wszystkich żądań , a następnie udekorowanie każdej akcji rolami, które mają dostęp do akcji ("biała lista"; zapobieganie dostępowi do wszystkich użytkowników, chyba że jest to dozwolone ręcznie). Teraz, jeśli programista zapomni o białej liście WŁAŚCIWEGO autoryzacja, użytkownicy dadzą Ci znać i jest to tak proste, jak przeglądanie innych kontrolerów w celu przypomnienia o tym, jak dać odpowiedni dostęp. Jednak przynajmniej nie ma większych luk w zabezpieczeniach.
W App_Start/FilterConfig.plik cs, zmodyfikuj klasę FilterConfig:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
...
//Deny access to all controllers and actions so that only logged in Administrators can access them by default
filters.Add(new System.Web.Mvc.AuthorizeAttribute() { Roles = "Administrator" });
}
To sprawia, że wszystkie działania są niedostępne, chyba że użytkownik jest zalogowany jako Administrator. Następnie dla każdej akcji, do której chcesz mieć dostęp inny upoważniony użytkownik, po prostu udekoruj ją [OverrideAuthorization]
i [Authorize]
.
W logice biznesowej pozwala to na używanie atrybutu Authorize na wiele sposobów bez konieczności martwienia się o nieautoryzowany dostęp użytkowników do jakichkolwiek funkcji. Poniżej kilka przykładów.
Przykład 1 -Tylko zalogowani użytkownicy administratora i dyspozytora będą mieli dostęp do metod Get i Post Index()
.
public class MarkupCalculatorController : Controller //Just continue using the default Controller class.
{
// GET: MarkupCalculator
[OverrideAuthorization]
[Authorize(Roles = "Administrator,Dispatcher")]
public ActionResult Index()
{
//Business logic here.
return View(...);
}
// POST: DeliveryFeeCalculator
[HttpPost]
[ValidateAntiForgeryToken]
[OverrideAuthorization]
[Authorize(Roles = "Administrator,Dispatcher")]
public ActionResult Index([Bind(Include = "Price,MarkedupPrice")] MarkupCalculatorVM markupCalculatorVM)
{
//Business logic here.
return View(...);
}
}
Przykład 2 - tylko uwierzytelnieni użytkownicy będą mogli uzyskać dostęp do kontrolera domowego Index()
metoda.
public class HomeController : Controller
{
[OverrideAuthorization]
[Authorize] //Allow all authorized (logged in) users to use this action
public ActionResult Index()
{
return View();
}
}
Przykład 3 -nieautoryzowani użytkownicy (np. anonimowi) mogą mieć dostęp do metod za pomocą atrybutu [AllowAnonymous]
. To również automatycznie nadpisuje filtr globalny bez potrzeby atrybutu [OverrideAuthorization]
.
// GET: /Account/Login
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
...
}
Przykład 4 - Tylko administratorzy będą mieli dostęp do metod, które nie posiadają atrybutu [Authorize]
.
public class LocationsController : Controller
{
// GET: Locations
public ActionResult Index()
{
//Business logic here.
return View(...);
}
}
Kilka uwag.
Musisz użyć atrybutu [OverrideAuthorization]
, jeśli chcesz ograniczyć dostęp do konkretnego działania do konkretnych ról. W przeciwnym razie, właściwości atrybutu [Authorize]
zostaną zignorowane i tylko domyślna rola (Administrator w moim przykładzie) będzie dozwolona, nawet jeśli określisz inne role (np. Dyspozytor, itd.) ze względu na filtr globalny. Nieautoryzowani użytkownicy zostaną przekierowani na ekran logowania.
Użycie atrybutu [OverrideAuthorization]
powoduje, że akcja ignoruje ustawiony filtr globalny. Dlatego musisz ponownie zastosować atrybut [Authorize]
za każdym razem, gdy używasz obejdź, aby akcja pozostała bezpieczna.
W odniesieniu do całych obszarów i kontrolerów
Aby ograniczyć obszary, jak prosisz, umieść atrybuty [OverrideAuthorization]
i [Authorize]
na kontrolerze zamiast poszczególnych akcji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-09 17:57:06
.. bardzo brutalnie, wierzę, że chcesz czegoś takiego?
Szybkie i brudne zarządzanie rolami
[Authorize(Roles = "Admins")]
public ActionResult Register()
{
ViewData["roleName"] = new SelectList(Roles.GetAllRoles(), "roleName");
ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
return View();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-23 15:10:47