2009-04-23 8 views
26

Mam kontroler i chciałbym, aby autoryzacja dla wszystkich działań była domyślnie za wyjątkiem pary. Tak więc w poniższym przykładzie wszystkie działania powinny wymagać uwierzytelnienia z wyjątkiem Indeksu. Nie chcę dekorować każdej akcji autoryzacją, chcę tylko zastąpić domyślną autoryzację w pewnych okolicznościach prawdopodobnie za pomocą niestandardowego filtru takiego jak NotAuthorize.ASP MVC Autoryzuj wszystkie działania poza kilkoma

[Authorize] 
public class HomeController : BaseController 
{ 
    [NotAuthorize] 
    public ActionResult Index() 
    { 
     // This one wont 
     return View(); 
    } 

    public ActionResult About() 
    { 
     // This action will require authorization 
     return View(); 
    } 
} 

Odpowiedz

37

Ok, właśnie to zrobiłem. Jeśli jest lepszy sposób, daj mi znać.

public class NotAuthorizeAttribute : FilterAttribute 
{ 
    // Does nothing, just used for decoration 
} 

public class BaseController : Controller 
{ 
    protected override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     // Check if this action has NotAuthorizeAttribute 
     object[] attributes = filterContext.ActionDescriptor.GetCustomAttributes(true); 
     if (attributes.Any(a => a is NotAuthorizeAttribute)) return; 

     // Must login 
     if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
     { 
      filterContext.Result = new HttpUnauthorizedResult(); 
     } 
    } 
} 
+15

myślę MVC4 kopiowane was, a teraz mamy [AllowAnonymous] –

+0

Wciąż pomocny wiedzieć przy tworzeniu niestandardowych funkcji walidacji w sterownikach niestandardowych :) – JDandChips

6

Oto, co bym zrobił, podobnie jak odpowiedź Craiga z kilkoma zmianami:

1) Utwórz zwykły atrybut powstałymi System.Attribute (nie ma potrzeby wynikają z FilterAttribute ponieważ nie są będzie używać niczego, co zapewnia funkcja FilterAttribute).

Może utworzyć hierarchię klas atrybutów, aby można było testować na podstawie hierarchii, np.

Attribute 
    AuthorizationAttribute 
     AuthorizationNotRequiredAttribute 
     AuthorizationAdminUserRequiredAttribute 
      AuthorizationSuperUserRequiredAttribute 

2) W swojej BaseController zastąpić metodę OnAuthorization zamiast metody OnActionExecuting:

protected override void OnAuthorization(AuthorizationContext filterContext) 
{ 
    var authorizationAttributes = filterContext.ActionDescriptor.GetCustomAttributes(true).OfType<AuthorizationAttribute>(); 
    bool accountRequired = !authorizationAttributes.Any(aa => aa is AuthorizationNotRequiredAttribute); 

Lubię podejście jest domyślnie zabezpieczone: nawet jeśli zapomnij umieścić atrybut w działaniu będzie to wymagało przynajmniej zalogowania użytkownika.

+1

jeśli nadpisuję OnAuthorization (AuthorizationContext filterContext), filterContext nie ma właściwości ActionDescriptor, więc nie mam pojęcia, jak znaleźć niestandardowe atrybuty z filtersContext? – spaceman

+0

Czy możesz potwierdzić, że jest to ASP.NET MVC 2? W V2 jest zdecydowanie ActionDescriptor. –

+0

Niestety, masz rację, nie mam jeszcze MVC 2. – spaceman

1

Nieco spóźniłem się na imprezę, ale w końcu utworzyłem atrybut autoryzacji na poziomie kontrolera i atrybut auth na poziomie działania i po prostu pomijam autoryzację kontrolera, jeśli Akcja miała swój własny atrybut Auth. Zobacz kod tutaj:

https://gist.github.com/948822

26

Co o [AllowAnonymous] ??

+0

Ten został utworzony później, ale jest teraz poprawną odpowiedzią. – Technetium

6

Użyj niestandardowego filtru zgodnie z opisem w dokumencie Securing your ASP.NET MVC 3 Application.

+1

Należy zauważyć, że odradza się udzielanie jedynie linków, odpowiedzi typu "przepełnienie stosu" powinny być punktem końcowym wyszukiwania rozwiązania (w przeciwieństwie do kolejnego zatrzymania odniesień, które z czasem stają się nieaktualne). –

5

Mark sterownik z [Autoryzacja]

[Autoryzuj] klasa publiczna YourController: ApiController

działania Oznacz chcesz publicznego z:

[AllowAnonymous]