HttpContext 标头

我创建了这个类来从请求中获取 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,因为它存储了由于单例而导致的旧标头值。我怎样才能解决这个问题?有没有其他方法可以做我正在做的事情。


LEATH
浏览 114回答 1
1回答

慕姐4208626

尝试使用HttpClientFactory添加了 Asp.Net Core 2.1 的 ,结合HttpMessageHandler以实现您正在尝试做的事情。ConfigureServices您可以在方法中注册 HttpClientpublic void ConfigureServices(IServiceCollection services){&nbsp; &nbsp; services.AddHttpClient<BaseClient>(client =>&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; client.BaseAddress = new Uri("yrl");&nbsp; &nbsp; &nbsp; &nbsp; client.DefaultRequestHeaders.Add("Accept", "application/json");&nbsp; &nbsp; &nbsp; &nbsp; c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");&nbsp; &nbsp; &nbsp; &nbsp; c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");&nbsp; &nbsp; });&nbsp;}使用上面的代码,您BaseClient将通过 DI 接收 HttpClient 实例。为了验证/检查,AuthHeader您可以HttpMessageHandler为已注册的HttpClient. 消息处理程序的代码很简单,如下所示:public class AuthHeaderHandler : DelegatingHandler{&nbsp; &nbsp; protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,&nbsp; &nbsp; &nbsp; &nbsp; CancellationToken cancellationToken)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (!request.Headers.Contains("Authorization"))&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new HttpResponseMessage(HttpStatusCode.Forbidden)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Content = new StringContent("No Authorization header is present")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return await base.SendAsync(request, cancellationToken);&nbsp; &nbsp; }}为了注册上述处理程序,您的代码将如下所示:public void ConfigureServices(IServiceCollection services){&nbsp; &nbsp; services.AddTransient<AuthHeaderHandler>();&nbsp; &nbsp; services.AddHttpClient<BaseClient>(client =>&nbsp; &nbsp; &nbsp;{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//code omitted for brevity&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;...&nbsp; &nbsp; &nbsp;})&nbsp; &nbsp; &nbsp; .AddHttpMessageHandler<AuthHeaderHandler>();&nbsp;}如果需要,您可以在消息处理程序中注入任何需要的内容。但是,无需在BaseClient. 要阅读有关 HttpClientFactory 和 HttpMessageHandlers 的更多信息,请参阅此链接和此。我希望这有帮助。更新的答案请查看使用 IHttpContextAccessor 并修改 HttpRequestMessage 的更具体的 HttpMessageHandler 示例,即在调用之前添加 Authorization 标头。您可以根据需要修改逻辑。public class AuthHeaderHandler : DelegatingHandler{&nbsp; &nbsp; private readonly HttpContext _httpContext;&nbsp; &nbsp; public AuthHeaderHandler(IHttpContextAccessor contextAccessor)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; _httpContext = contextAccessor.HttpContext;&nbsp; &nbsp; }&nbsp; &nbsp; protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,&nbsp; &nbsp; &nbsp; &nbsp; CancellationToken cancellationToken)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (_httpContext != null)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var accessToken = await _httpContext.GetTokenAsync(TokenKeys.Access);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!string.IsNullOrEmpty(accessToken))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // modify the request header with the new Authorization token&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return await base.SendAsync(request, cancellationToken);&nbsp; &nbsp; }}更新的答案 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{&nbsp; &nbsp; private readonly MyHttpClient _client;&nbsp; &nbsp; public DataController(MyHttpClient client)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; _client = client;&nbsp; &nbsp; }&nbsp; &nbsp; [ValidateAuthHeader]&nbsp; &nbsp; public async Task<IActionResult> GetValues()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var response = await _client.GetAsync("api/values");&nbsp; &nbsp; &nbsp; &nbsp; var contents = await response.Content.ReadAsStringAsync();&nbsp; &nbsp; &nbsp; &nbsp; return new ContentResult&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Content = contents,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ContentType = "application/json",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; StatusCode = 200&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; }}流程的其余部分与我最初建议的相同。调用将通过AuthHeaderHandler已HttpMessageHandler注册的MyHttpClient. 请看一看Startup.cs。处理程序将检索HttpContextviaHttpContextAccessor并检查AuthHeader. 如果存在,它将把它添加到 RequestMessage 参数中。我希望这有帮助。如有任何问题,请随时提出。不使用 HttpMessageHandler 设置 Auth Header修改 MyHttpClient 并添加一个名为的公共方法SetAuthHeaderpublic class MyHttpClient{&nbsp; &nbsp; private readonly HttpClient _httpClient;&nbsp; &nbsp; public MyHttpClient(HttpClient client)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; _httpClient = client;&nbsp; &nbsp; }&nbsp; &nbsp; public void SetAuthHeader(string value)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", value);&nbsp; &nbsp; }}然后在您的操作方法中调用此方法,因为此时您将在 HttpContext.Request 中拥有 AuthHeader[ValidateAuthHeader]public async Task<IActionResult> GetValues(){&nbsp; &nbsp; var authHeader = Request.Headers["Authorization"];&nbsp; &nbsp; _client.SetAuthHeader(authHeader.First());&nbsp; &nbsp; var response = await _client.GetAsync("api/values");&nbsp; &nbsp; var contents = await response.Content.ReadAsStringAsync();&nbsp; &nbsp; return new ContentResult&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; Content = contents,&nbsp; &nbsp; &nbsp; &nbsp; ContentType = "application/json",&nbsp; &nbsp; &nbsp; &nbsp; StatusCode = 200&nbsp; &nbsp; };}去掉AuthHeaderHandler注册,删除AuthHeaderHandler。
打开App,查看更多内容
随时随地看视频慕课网APP