C# 如何在DelegatingHandler中读取发送给操作方法(WebAPI)的参数
我正在使用IHttpClientFactory通过netcore2.2从外部api发送请求和接收HTTP响应 我已经实现了一个DelegatingHandler来“拦截”我的http请求并添加授权头(令牌)。如果令牌无效,它将获取一个新令牌并重试一次 同样,当我第一次获得一个新的令牌时,我会将该令牌缓存在内存中以供进一步引用。为了缓存令牌,我创建了一个需要accountID和令牌的字典 我遇到的问题是DelegatingHandler在Startup.cs类中注册,但此时我没有accountID,我将accountID作为控制器ActionMethod中的参数获取。该操作方法调用SendAsync并从DelegatingHandler获取令牌,以此类推 我不知道,在控制器收到请求后,如何将accountID注入DelegatingHandler 我试图创建一个IClientCredentials接口和该接口的一个实现,该接口可以在控制器中实例化并注入DelegatingHandler 我的代码如下所示: 委托人:C# 如何在DelegatingHandler中读取发送给操作方法(WebAPI)的参数,c#,asp.net-core,dependency-injection,token,httpclientfactory,C#,Asp.net Core,Dependency Injection,Token,Httpclientfactory,我正在使用IHttpClientFactory通过netcore2.2从外部api发送请求和接收HTTP响应 我已经实现了一个DelegatingHandler来“拦截”我的http请求并添加授权头(令牌)。如果令牌无效,它将获取一个新令牌并重试一次 同样,当我第一次获得一个新的令牌时,我会将该令牌缓存在内存中以供进一步引用。为了缓存令牌,我创建了一个需要accountID和令牌的字典 我遇到的问题是DelegatingHandler在Startup.cs类中注册,但此时我没有accountID
public class AuthenticationDelegatingHandler : DelegatingHandler
{
private readonly AccessTokenManager _accessTokenManager;
private readonly IClientCredentials _clientCredentials;
public AuthenticationDelegatingHandler(IHttpClientFactory httpClientFactory,
IOptions<AppSettings> appSettings, IClientCredentials clientCredentials)
{
_accessTokenManager = new AccessTokenManager(httpClientFactory, appSettings);
_clientCredentials = clientCredentials;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var clientCredentials = _clientCredentials.GetClientCredentials();
var accessToken = _accessTokenManager.GetToken(clientCredentials._accountID);
if (accessToken == null) {
accessToken = await _accessTokenManager.GetAccessTokenAsync(clientCredentials._accountID);
_accessTokenManager.AddOrUpdateToken(clientCredentials._accountID, accessToken);
}
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.access_token);
var response = await base.SendAsync(request, cancellationToken);
if (response.StatusCode == HttpStatusCode.Unauthorized || response.StatusCode == HttpStatusCode.Forbidden)
{
var token = await _accessTokenManager.GetAccessTokenAsync(clientCredentials._accountID);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.access_token);
response = await base.SendAsync(request, cancellationToken);
}
return response;
}
}
公共类身份验证DelegatingHandler:DelegatingHandler
{
私有只读AccessTokenManager\u AccessTokenManager;
专用只读IClientCredentials _客户端凭据;
公共身份验证DelegatingHandler(IHttpClientFactory httpClientFactory,
IOOptions应用程序设置、IClientCredentials客户端凭据)
{
_accessTokenManager=新的accessTokenManager(httpClientFactory,appSettings);
_clientCredentials=clientCredentials;
}
受保护的覆盖异步任务SendAsync(HttpRequestMessage请求,CancellationToken CancellationToken)
{
var clientCredentials=_clientCredentials.GetClientCredentials();
var accessToken=\u accessTokenManager.GetToken(clientCredentials.\u accountID);
如果(accessToken==null){
accessToken=await\u accessTokenManager.GetAccessTokenAsync(客户端凭据.\u帐户ID);
_accessTokenManager.AddOrUpdateToken(客户端凭据。\u accountID,accessToken);
}
request.Headers.Authorization=新的AuthenticationHeaderValue(“承载者”,accessToken.access\u令牌);
var response=await base.sendaync(请求、取消令牌);
if(response.StatusCode==HttpStatusCode.Unauthorized | | response.StatusCode==HttpStatusCode.Forbidden)
{
var token=await\u accessTokenManager.GetAccessTokenAsync(clientCredentials.\u accountID);
request.Headers.Authorization=新的AuthenticationHeaderValue(“承载者”,token.access\u token);
response=wait base.sendaync(请求、取消令牌);
}
返回响应;
}
}
Startup.cs类似于:
services.AddScoped<IClientCredentials>(_ => new
ClientCredentials("au","123"));
services.AddHttpClient("myClient")
.AddHttpMessageHandler<AuthenticationDelegatingHandler>();
services.AddScoped(=>new)
客户证书(“au”、“123”);
服务。AddHttpClient(“myClient”)
.AddHttpMessageHandler();
以及控制器:
[HttpPost("{siteName}/{accountID}")]
public async Task<ActionResult<AirRequest>> Post(AirModel model, string
siteName, string accountID)
{
....
SetClientCredentials(siteName, accountID);
var clientJAAPI =
_httpClientFactory.CreateClient("myClient");
var responseclientJAAPI = await
clientJAAPI.SendAsync(request);
.....
}
private ClientCredentials SetClientCredentials(string siteName, string
accountID) =>
new ClientCredentials(siteName, accountID);
this.HttpContext.Items["accountId"] = accountId;
[HttpPost(“{siteName}/{accountID}”)]
公共异步任务Post(AirModel模型,字符串
站点名称、字符串帐户ID)
{
....
SetClientCredentials(站点名称、帐户ID);
var clientJAAPI=
_httpClientFactory.CreateClient(“myClient”);
var responseclientJAAPI=等待
clientJAAPI.SendAsync(请求);
.....
}
private ClientCredentials SetClientCredentials(字符串siteName,字符串
帐户ID)=>
新客户端凭据(站点名称、帐户ID);
您可以使用HttpContext.Items
传递数据。
(未测试,由手机发送)。
在控制器中:
[HttpPost("{siteName}/{accountID}")]
public async Task<ActionResult<AirRequest>> Post(AirModel model, string
siteName, string accountID)
{
....
SetClientCredentials(siteName, accountID);
var clientJAAPI =
_httpClientFactory.CreateClient("myClient");
var responseclientJAAPI = await
clientJAAPI.SendAsync(request);
.....
}
private ClientCredentials SetClientCredentials(string siteName, string
accountID) =>
new ClientCredentials(siteName, accountID);
this.HttpContext.Items["accountId"] = accountId;
在处理程序中注入IHttpContextAccessor
var accountId = _httpContextAccessor.HttpContext.Items["accountId"];
默认情况下,IHttpContextAccessor未注册,但可以由您正在使用的组件之一注册。如果出现异常,请在DI中明确注册它:
services.AddHttpContextAccessor();
如果缺少IHttpContextAccessor类型,请添加Microsoft.AspNetCore.Http
nuget
数据将一直保存到请求结束 您可以使用
HttpContext.Items
传递数据。
(未测试,由手机发送)。
在控制器中:
[HttpPost("{siteName}/{accountID}")]
public async Task<ActionResult<AirRequest>> Post(AirModel model, string
siteName, string accountID)
{
....
SetClientCredentials(siteName, accountID);
var clientJAAPI =
_httpClientFactory.CreateClient("myClient");
var responseclientJAAPI = await
clientJAAPI.SendAsync(request);
.....
}
private ClientCredentials SetClientCredentials(string siteName, string
accountID) =>
new ClientCredentials(siteName, accountID);
this.HttpContext.Items["accountId"] = accountId;
在处理程序中注入IHttpContextAccessor
var accountId = _httpContextAccessor.HttpContext.Items["accountId"];
默认情况下,IHttpContextAccessor未注册,但可以由您正在使用的组件之一注册。如果出现异常,请在DI中明确注册它:
services.AddHttpContextAccessor();
如果缺少IHttpContextAccessor类型,请添加Microsoft.AspNetCore.Http
nuget
数据将一直保存到请求结束