为了账号安全,请及时绑定邮箱和手机立即绑定

HttpContext 标头

HttpContext 标头

C#
LEATH 2022-12-24 14:47:10
我创建了这个类来从请求中获取 Header 值。public class AuthenticationHeader{    private static  IHttpContextAccessor _httpContextAccessor;    public AuthenticationHeader(IHttpContextAccessor httpContextAccessor)    {        _httpContextAccessor = httpContextAccessor;    }    public string AuthHeader => _httpContextAccessor.HttpContext?.Request.Headers["Authorization"];}并且我已经像这样在我的 startup.cs 中注册了它services.AddSingleton<AuthenticationHeader>();它像这样被注入到我的其他课程中。public BaseClient(HttpClient client, ILogger<BaseClient> logger, AuthenticationHeader authHeader){    _client = client;    client.BaseAddress = new Uri("yrl");    client.DefaultRequestHeaders.Add("Accept", "application/json");    _logger = logger;    AuthHeader = authHeader;}现在我已经将其注册为Singleton. 因此,当第一次调用我的 Api 并在标头中提供授权值时,api 被成功调用,但问题是当我传递空的授权标头时,它仍然成功调用了 api,因为它存储了由于单例而导致的旧标头值。我怎样才能解决这个问题?有没有其他方法可以做我正在做的事情。
查看完整描述

1 回答

?
慕姐4208626

TA贡献1852条经验 获得超7个赞

尝试使用HttpClientFactory添加了 Asp.Net Core 2.1 的 ,结合HttpMessageHandler以实现您正在尝试做的事情。


ConfigureServices您可以在方法中注册 HttpClient


public void ConfigureServices(IServiceCollection services)

{

    services.AddHttpClient<BaseClient>(client =>

    {

        client.BaseAddress = new Uri("yrl");

        client.DefaultRequestHeaders.Add("Accept", "application/json");

        c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");

        c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");

    });

 }

使用上面的代码,您BaseClient将通过 DI 接收 HttpClient 实例。


为了验证/检查,AuthHeader您可以HttpMessageHandler为已注册的HttpClient. 消息处理程序的代码很简单,如下所示:


public class AuthHeaderHandler : DelegatingHandler

{

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,

        CancellationToken cancellationToken)

    {

        if (!request.Headers.Contains("Authorization"))

        {

            return new HttpResponseMessage(HttpStatusCode.Forbidden)

            {

                Content = new StringContent("No Authorization header is present")

            };

        }


        return await base.SendAsync(request, cancellationToken);

    }

}

为了注册上述处理程序,您的代码将如下所示:


public void ConfigureServices(IServiceCollection services)

{

    services.AddTransient<AuthHeaderHandler>();

    services.AddHttpClient<BaseClient>(client =>

     {

         //code omitted for brevity

         ...

     })

      .AddHttpMessageHandler<AuthHeaderHandler>();

 }

如果需要,您可以在消息处理程序中注入任何需要的内容。但是,无需在BaseClient. 要阅读有关 HttpClientFactory 和 HttpMessageHandlers 的更多信息,请参阅此链接和此。我希望这有帮助。


更新的答案


请查看使用 IHttpContextAccessor 并修改 HttpRequestMessage 的更具体的 HttpMessageHandler 示例,即在调用之前添加 Authorization 标头。您可以根据需要修改逻辑。


public class AuthHeaderHandler : DelegatingHandler

{

    private readonly HttpContext _httpContext;


    public AuthHeaderHandler(IHttpContextAccessor contextAccessor)

    {

        _httpContext = contextAccessor.HttpContext;

    }


    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,

        CancellationToken cancellationToken)

    {

        if (_httpContext != null)

        {

            var accessToken = await _httpContext.GetTokenAsync(TokenKeys.Access);

            if (!string.IsNullOrEmpty(accessToken))

            {

                // modify the request header with the new Authorization token

                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

            }

        }


        return await base.SendAsync(request, cancellationToken);

    }

}

更新的答案 2


请查看我已上传到 GitHub的简单解决方案。该解决方案甚至比我最初建议的还要简单。由于您没有集成任何基于身份的身份验证/授权,您可以简单地使用我称之为 CustomActionFilter 的 CustomActionFilterValidateAuthHeader来检查 AuthHeader 是否存在,如果不存在则返回通常的 403。


在 中ValidateAuthHeader,我使用了您之前发布的中间件代码。然后,您可以简单地将此属性添加到需要此检查的 ActionMethods 或 Controllers 上。


请查看DataController和ValuesController。将DataController接收HttpClient将用于调用values端点的类型。ValidateAuthHeader出现在 上GetValues并将检查 AuthHeader。如果它不存在,它将产生错误。


[Route("api/[controller]")]

[ApiController]

public class DataController : ControllerBase

{

    private readonly MyHttpClient _client;


    public DataController(MyHttpClient client)

    {

        _client = client;

    }


    [ValidateAuthHeader]

    public async Task<IActionResult> GetValues()

    {

        var response = await _client.GetAsync("api/values");


        var contents = await response.Content.ReadAsStringAsync();


        return new ContentResult

        {

            Content = contents,

            ContentType = "application/json",

            StatusCode = 200

        };

    }

}

流程的其余部分与我最初建议的相同。调用将通过AuthHeaderHandler已HttpMessageHandler注册的MyHttpClient. 请看一看Startup.cs。


处理程序将检索HttpContextviaHttpContextAccessor并检查AuthHeader. 如果存在,它将把它添加到 RequestMessage 参数中。


我希望这有帮助。如有任何问题,请随时提出。


不使用 HttpMessageHandler 设置 Auth Header


修改 MyHttpClient 并添加一个名为的公共方法SetAuthHeader


public class MyHttpClient

{

    private readonly HttpClient _httpClient;


    public MyHttpClient(HttpClient client)

    {

        _httpClient = client;

    }


    public void SetAuthHeader(string value)

    {

        _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", value);

    }

}

然后在您的操作方法中调用此方法,因为此时您将在 HttpContext.Request 中拥有 AuthHeader


[ValidateAuthHeader]

public async Task<IActionResult> GetValues()

{

    var authHeader = Request.Headers["Authorization"];


    _client.SetAuthHeader(authHeader.First());


    var response = await _client.GetAsync("api/values");


    var contents = await response.Content.ReadAsStringAsync();


    return new ContentResult

    {

        Content = contents,

        ContentType = "application/json",

        StatusCode = 200

    };

}

去掉AuthHeaderHandler注册,删除AuthHeaderHandler。


查看完整回答
反对 回复 2022-12-24
  • 1 回答
  • 0 关注
  • 112 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信