15

我有一个名为 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
}

这样的事情可能吗?

4

4 回答 4

21

There is a way to do this _in ASP.NET MVC_ with action-methods (not with attributes in general)

public class CustomAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        int userId = (int)filterContext.ActionParameters["userId"];
    }
}
于 2014-12-05T22:26:23.240 回答
17

让 vcsjones 的评论成为答案,这是不可能的。

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

The one way this would work is to make the attribute an AOP element, using a framework like PostSharp or rolling your own with the Unity Framework etc. This would allow you to attach an "interceptor" to the method by decorating it with an attribute, which will then run code in the attribute and will also have knowledge about exactly how the method was called including parameter values. Check out this blog: http://www.progware.org/Blog/post/Interception-and-Interceptors-in-C-(Aspect-oriented-programming).aspx

于 2012-05-03T16:31:00.243 回答
0

I was able to get around this by using the following:

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

And then on the specific methods you want to check Ids on,

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

And if you don't care to check their Id, but just that they're authenticated

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

Of course you can organize your authorize procedure however you like but this idea allows you to get their ID in your auth procedure there since it is passed in as route data. More here: https://stackoverflow.com/a/16054886

于 2018-02-01T13:54:43.537 回答
0

Probably because this is an old post but this is now possible

[MyAttribute(MyAttributeVar= "myMethodVar")]
public void MyMethod(int myMethodVar)
于 2020-12-07T11:27:08.923 回答