How to plug method parameters into custom attribute

蹲街弑〆低调 提交于 2019-12-21 07:19:14

问题


I have a custom Attribute called AuthoriseAttribute whose constructor looks like this:

public AuthoriseAttribute(int userId)
{
  .. blah
}

This is used with a method called GetUserDetails() like this:

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

At runtime, the presence of the Authorise attribute causes some authorisation code to execute which requires the ID of the user. Obviously, this can be extracted from the parameter of the GetUserDetails() method, but this means that the authorisation code depends on the method's parameter being given a particular name.

I would like to be able to pass in the actual value of the userId parameter into the attribute, so that the authorisation code works with the value passed in to the attribute (i.e. not the method parameter), whose name is known.

Something like this (which doesn't work):

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

Is such a thing possible?


回答1:


Making vcsjones' comment an answer, this is not possible.

Attributes are metadata; they are compiled into the assembly at compile-time and do not change during runtime. As such, any parameters you pass into an attribute must be constants; literals, constant variables, compiler defines, etc.

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




回答2:


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"];
    }
}



回答3:


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



来源:https://stackoverflow.com/questions/10435403/how-to-plug-method-parameters-into-custom-attribute

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!