2012-05-03 34 views
9

我有一个名为AuthoriseAttribute它的构造看起来像这样的自定义属性:如何插入方法的参数为自定义属性

public AuthoriseAttribute(int userId) 
{ 
    .. blah 
} 

这是使用一种称为GetUserDetails()这样的:

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

在运行时,Authorize属性的存在会导致执行一些授权代码,这需要用户的ID。显然,这可以从GetUserDetails()方法的参数被提取,但是这意味着该授权码依赖于方法的参数被赋予一个特定的名称。

我希望能够将userId参数的实际值传递给属性,以便授权代码使用传递给属性(即不是方法参数)的值,该值的名称是已知的。

这样的事情(不工作):

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

这种事可能吗?

+5

没有不可能的。属性是元数据。参数值必须是一个常数值。 – vcsjones

+0

有一些我不明白的 - 你为什么要授权一个方法参数?海事组织 - 你可能需要授权方法的调用者 - 这是正确的吗? – Sunny

+2

您所描述的内容不能直接完成,因为我确定编译器错误告诉您。了解“授权属性的存在是如何导致某些授权代码执行”的工作是有帮助的。你应该可以让代码看看userId参数。 –

回答

12

制作vcsjones'评论的答案,这是不可能的。

属性是元数据;它们在编译时编译到程序集中,并且在运行时不会更改。因此,您传递给属性的任何参数都必须是常量;文字,常量变量,编译器定义等。

这种方法的一种方式是使用像PostSharp这样的框架或使用Unity Framework滚动自己的属性来使属性成为AOP元素。这将允许您附加该方法的一个“拦截器”通过用属性装饰来实现,然后该属性将在属性中运行代码,并且还将知道如何调用包括参数值的方法。查看此博客:http://www.progware.org/Blog/post/Interception-and-Interceptors-in-C-(Aspect-oriented-programming).aspx

+0

你偷了vcsjones的答案,我会奖励你的!我确实已经把AOP的东西运行起来了;我的问题是告诉拦截器中的代码在哪里找到它需要运行授权逻辑的数据,因为这个属性可能被用来装饰不同签名的多个方法。 – David

+7

我不会说这是偷窃。 +1,以便接受我的评论并将其转化为有用的答案。 – vcsjones

+0

+1是一项很好的运动。 – David

14

一个办法做到这一点_in ASP.NET MVC_与行动的方法(不是一般的属性)

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

这工作正常,谢谢! –

0

我能通过使用以下内容来解决此问题:

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

然后在具体的方法上你想检查ID,

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

如果你不小心检查他们的身份证,只是,他们正在验证

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

当然,只要你喜欢,你可以组织你的授权过程,但这个想法让你因为它是作为路由数据传入的,所以在你的认证过程中得到他们的ID。 这里更多:https://stackoverflow.com/a/16054886

相关问题