gpt4 book ai didi

c# - HttpContext 头

转载 作者:行者123 更新时间:2023-12-04 15:45:55 35 4
gpt4 key购买 nike

我创建了这个类来从请求中获取 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>();

它像这样被注入(inject)到我的其他类中。
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 并在 header 中提供 Authorization 值时,api 被成功调用,但问题是当我传递空的 Authorization header 时,它仍然成功调用了 api,因为它由于单例存储了旧的 header 值。我怎样才能解决这个问题?有没有其他方法可以做我正在做的事情。

最佳答案

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

您可以在 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>();
}

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

更新的答案

请查看使用 IHttpContextAccessor 并修改 HttpRequestMessage 的 HttpMessageHandler 的更具体示例,即在调用之前添加 Authorization header 。您可以根据需要修改逻辑。
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

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

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

请查看 DataControllerValuesController . 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 .

处理程序将检索 HttpContext来自 HttpContextAccessor并将检查 AuthHeader .如果存在,它会将其添加到 RequestMessage 参数中。

我希望这有帮助。随时提出您可能有的任何问题。

在不使用 HttpMessageHandler 的情况下设置 Auth header

修改 MyHttpClient 并添加一个名为 SetAuthHeader 的公共(public)方法
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。

关于c# - HttpContext 头,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55810466/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com