2012-05-03 19 views
9

Mam niestandardowy atrybut o nazwie AuthoriseAttribute którego konstruktor wygląda następująco:Jak podłączyć parametry metody do atrybutu niestandardowego

public AuthoriseAttribute(int userId) 
{ 
    .. blah 
} 

ta jest stosowana z metodą zwaną GetUserDetails() takiego:

[Authorise(????????)] 
public UserDetailsDto GetUserDetails(int userId) 
{ 
    .. blah 
} 

Na środowisko wykonawcze, obecność atrybutu Autoryzuj powoduje uruchomienie kodu autoryzacyjnego, który wymaga identyfikatora użytkownika. Oczywiście można to wyodrębnić z parametru metody GetUserDetails(), ale oznacza to, że kod autoryzacji zależy od parametru danej metody, któremu nadano konkretną nazwę.

Chciałbym móc przekazać rzeczywistą wartość parametru userId do atrybutu, tak aby kod autoryzacji działał z wartością przekazaną do atrybutu (tj. Nie do parametru metody), którego nazwa jest znana. .

Coś jak ten (który nie działa):

[Authorise(userId)] 
public UserDetailsDto GetUserDetails(int userId) 
{ 
    .. blah 
} 

Czy coś takiego jest możliwe?

+5

Nie jest to niemożliwe. Atrybuty to metadane. Wartości parametrów muszą być wartością stałą. – vcsjones

+0

Jest coś, czego nie rozumiem - dlaczego miałbyś chcieć autoryzować parametr metody?IMO - może być konieczne autoryzowanie wywołującego metody - czy to prawda? – Sunny

+2

To, co opisujesz, nie może zostać wykonane bezpośrednio, ponieważ jestem pewny, że błąd kompilatora ci powiedział. Przydałoby się wiedzieć, jak działa "obecność atrybutu Autoryzuj powoduje uruchomienie kodu autoryzacyjnego". Powinieneś być w stanie odczytać kod w parametrze userId. –

Odpowiedz

12

Dokonanie komentarza Vcsjonesa jest odpowiedzią, nie jest to możliwe.

Atrybuty są metadanymi; są one kompilowane podczas kompilacji podczas kompilacji i nie zmieniają się podczas działania. W związku z tym wszelkie parametry przekazywane do atrybutu muszą być stałe; literały, stałe zmienne, kompilator definiuje, itp.

Jednym ze sposobów, w jaki mogłoby to działać, jest uczynienie z atrybutu elementu AOP, użycie frameworka takiego jak PostSharp lub rozwijanie własnego z Unity Framework itp. Umożliwiłoby to dołączenie "przechwytywacz" do metody, dekorując go atrybutem, który następnie uruchomi kod w atrybucie i będzie również posiadał wiedzę o tym, jak dokładnie metoda została wywołana, w tym wartości parametrów. Sprawdź ten blog: http://www.progware.org/Blog/post/Interception-and-Interceptors-in-C-(Aspect-oriented-programming).aspx

+0

Ukradłeś odpowiedź Vcsjonesa, a ja ci za to wynagrodzę! Mam uruchomione rzeczy AOP; mój problem polega na informowaniu kodu w przechwytywaczu, gdzie znaleźć dane potrzebne do uruchomienia logiki autoryzacji, ponieważ atrybut ten może być użyty do dekoracji wielu metod z różnymi sygnaturami. – David

+7

Nie powiedziałbym, że to kradzież. +1 za wzięcie mojego komentarza i przekształcenie go w przydatną odpowiedź. – vcsjones

+0

+1 za bycie dobrym sportem. – David

14

Nie jest sposób zrobić to _in ASP.NET MVC_ z metod akcji (nie w przypadku atrybutów w ogóle)

public class CustomAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     int userId = (int)filterContext.ActionParameters["userId"]; 
    } 
} 
+0

to działa dobrze, dzięki! –

0

Mogłem obejść to, używając:

public class AuthorizeAttribute 
{ 
    protected bool RequireIdClaim { get; private set; } 

    public AuthorizeAttribute(bool requireIdClaim = false) 
    { 
     RequireIdClaim = requireIdClaim; 
    } 

    public Authorize() 
    { 
     //regular auth stuff here 

     if (RequireIdClaim) 
     { 
      var routeData = context.ActionContext.Request.GetRouteData(); 
      var requiredIdClaim = Convert.ToInt32(routeData.Values["id"]); 

      //Check here if their user profile has a claim to that Id 
     } 
    } 
} 

A następnie konkretnych metod, które chcesz sprawdzić Ids na,

[HttpGet] 
[Route("{id}")] 
[Authorize(requireIdClaim: true)] 
public UserDetailsDto GetUserDetails(int userId) 
{ 
    .. blah 
} 

A jeśli nie obchodzi, aby sprawdzić ich osobistego, ale tylko, że są one uwierzytelnione

[HttpGet] 
[Route("")] 
[Authorize] 
public bool isLoggedIn() 
{ 
    .. blah 
} 

oczywiście można zorganizować procedurę autoryzacji jednak chcesz, ale idea ta pozwala na weź tam swój identyfikator w procedurze auth, ponieważ jest on przekazywany jako dane trasy. Więcej tutaj: https://stackoverflow.com/a/16054886

Powiązane problemy