有没有一种方法可以将请求标头指定为ASP.NET Core Controller操作参数/参数?

时间:2019-12-15 19:25:20

标签: c# asp.net-core .net-core

我的控制器操作如下:

[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}")]
public class StuffController : ControllerBase
{
    [HttpGet("stuff/")]
    [Authorize(Roles = "admin,read-stuff")]
    [Produces("application/json")]
    [ProducesResponseType(typeof(IActionResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status403Forbidden)]
    public async Task<IActionResult> Get()
    {
        var authorization = Request.Headers["authorization"];
        var accessToken = authorization[0].Replace("Bearer ", string.Empty);

        // use accessToken for token exchange
        // use the new token another to get and return the actual results
    }
}

我想知道是否有一个技巧可以像操作参数中那样直接使用承载/访问令牌,例如:

[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}")]
public class StuffController : ControllerBase
{
    [HttpGet("stuff/")]
    [Authorize(Roles = "admin,read-stuff")]
    [Produces("application/json")]
    [ProducesResponseType(typeof(IActionResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status403Forbidden)]
    public async Task<IActionResult> Get([BearerTokenHeader] string bearerTokenHeader)
    {
        // use accessToken for token exchange
        // use the new token another to get and return the actual results
    }
}

2 个答案:

答案 0 :(得分:2)

添加自定义属性,值提供者:

[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class BearerTokenFromHeaderAttribute : Attribute, IBindingSourceMetadata, IModelNameProvider
{
    public BindingSource BindingSource => BearerTokenBindingSource.Instance;

    public string Name { get; set; }
}

public static class BearerTokenBindingSource
{
    public static readonly BindingSource Instance = new BindingSource(
        "BearerToken",
        "BearerToken",
        isGreedy: false,
        isFromRequest: true);
}

public class BearerTokenValueProviderFactory : IValueProviderFactory
{
    public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
    {
        var authorizationHeader = context.ActionContext.HttpContext.Request.Headers["Authorization"];
        var accessToken = authorizationHeader[0].Replace("Bearer ", string.Empty);

        context.ValueProviders.Add(new BearerTokenValueProvider(BearerTokenBindingSource.Instance, accessToken));

        return Task.CompletedTask;
    }
}

public class BearerTokenValueProvider : BindingSourceValueProvider
{
    public BearerTokenValueProvider(BindingSource bindingSource, string accessToken) : base(bindingSource)
    {
        AccessToken = accessToken;
    }

    private string AccessToken { get; }

    public override bool ContainsPrefix(string prefix)
    {
        return false;
    }

    public override ValueProviderResult GetValue(string key)
    {
        return new ValueProviderResult(AccessToken);
    }
}

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddMvc(options =>
    {
        options.ValueProviderFactories.Add(new BearerTokenValueProviderFactory());
    });
}

控制器

[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}")]
public class StuffController : ControllerBase
{
    [HttpGet("stuff/")]
    [Authorize(Roles = "admin,read-stuff")]
    [Produces("application/json")]
    [ProducesResponseType(typeof(IActionResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status403Forbidden)]
    public async Task<IActionResult> Get([BearerTokenFromHeader] string accessToken)
    {
        // use accessToken for token exchange
        // use the new token another to get and return the actual results
    }
}

答案 1 :(得分:1)

尝试像这样[FromHeader]绑定源参数:[FromHeader] string authorization