2012-05-03 12 views
9

Tengo un atributo personalizado denominado AuthoriseAttribute cuyo constructor se ve así:Cómo conectar los parámetros del método en atributo personalizado

public AuthoriseAttribute(int userId) 
{ 
    .. blah 
} 

Esto se utiliza con un método llamado GetUserDetails() así:

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

En tiempo de ejecución, la presencia del atributo Authorize provoca la ejecución de algún código de autorización que requiere la identificación del usuario. Obviamente, esto se puede extraer del parámetro del método GetUserDetails(), pero esto significa que el código de autorización depende de que al parámetro del método se le dé un nombre particular.

Me gustaría poder pasar el valor real del parámetro userId en el atributo, para que el código de autorización funcione con el valor pasado al atributo (es decir, no el parámetro del método), cuyo nombre se conoce .

Algo como esto (que no funciona):

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

¿Es posible tal cosa?

+5

No, no es posible. Los atributos son metadatos. Los valores de los parámetros deben ser un valor constante. – vcsjones

+0

Hay algo que no entiendo: ¿por qué querrías autorizar un parámetro de método?OMI: es posible que deba autorizar a la persona que llama del método: ¿es correcto? – Sunny

+2

Lo que describes no se puede hacer directamente, ya que estoy seguro de que el error del compilador te lo comunicó. Sería útil saber cómo está funcionando la frase "la presencia del atributo Autorizar hace que se ejecute algún código de autorización". Debería poder tener el código ahí para ver el parámetro userId. –

Respuesta

12

Haciendo el comentario de vcsjones una respuesta, esto no es posible.

Los atributos son metadatos; se compilan en el ensamblado en tiempo de compilación y no cambian durante el tiempo de ejecución. Como tal, cualquier parámetro que pases a un atributo debe ser constantes; literales, variables constantes, compilador define, etc.

La única forma en que esto funcionaría es hacer que el atributo sea un elemento AOP, utilizando un marco como PostSharp o el propio con el Unity Framework etc. Esto le permitiría adjuntar un "interceptor" del método al decorarlo con un atributo, que luego ejecutará el código en el atributo y también tendrá conocimiento sobre cómo se llamó exactamente el método, incluidos los valores de los parámetros. Echa un vistazo a este blog: http://www.progware.org/Blog/post/Interception-and-Interceptors-in-C-(Aspect-oriented-programming).aspx

+0

¡Has robado la respuesta de vcsjones y te recompensaré por ello! Tengo las cosas de AOP en funcionamiento; mi problema es decirle al código en el interceptor dónde encontrar los datos que necesita para ejecutar la lógica de autorización, ya que el atributo podría usarse para decorar múltiples métodos con diferentes firmas. – David

+7

No diría que es un robo. +1 por tomar mi comentario y convertirlo en una respuesta útil. – vcsjones

+0

+1 por ser un buen deporte. – David

14

Hay es una manera de hacer esto _en ASP.NET MVC_ con acción-métodos (no con atributos en general)

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

esto está funcionando bien, gracias! –

0

pude evitar esto mediante el uso de lo siguiente:

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 
     } 
    } 
} 

Y luego sobre los métodos específicos que desea comprobar documentos de identidad al,

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

Y si no le importa para comprobar su identificación, pero sólo que está autenticado

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

Por supuesto que puede organizar su procedimiento de autorizar como usted quiera, pero esta idea que permite a obtenga su ID en su procedimiento de autenticación allí ya que se transfiere como datos de ruta. Más aquí: https://stackoverflow.com/a/16054886

Cuestiones relacionadas