从IHttpContextAccessor的HttpContext同步获取AccessToken

时间:2019-04-16 14:46:00

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

我们正在使用ASP.NET Core 2.2构建一个Web API项目,该项目实际上是另一个API的智能代理。不过,我们不想对访问令牌做任何特殊的事情,而只是在调用其他API时将其转发。

我想避免“通过异步进行同步”调用,尤其是在构造函数,DI解析器和工厂中,同时仍要依靠该框架来处理从当前http请求中获取访问令牌的过程。

以下是我们场景的典型代表:

 const https = require("https");

const data = JSON.stringify({
  key: "value"
});

const options = {
  hostname: "url",
  port: 443,
  path: "/path",
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Content-Length": data.length
  }
};

const req = https.request(options, res => {
  console.log(
    `statusCode: ${res.statusCode} statusMessage: ${res.statusMessage}`
  );
  res.setEncoding("utf8");
  res.on("data", chunk => {
    console.log(chunk);
  });
});

req.on("error", error => {
  console.error(error);
});
req.write(data)
req.end();

public class TheOtherApi : ITheOtherApi { private readonly HttpClient _client; public TheOtherApi(HttpClient client, IHttpContextAccessor httpContextAccessor) { _client = client; // Yuck! Sync over async, inside a constructor! var token = httpContextAccessor.HttpContext.GetTokenAsync("access_token").Result; client.SetBearerToken(token); } public Task<string> ForwardSomethingCool(MyCommand command) { // E.g. var response await _client.PostAsync(command.path, command.body); return await response.Content.ReadAsStringAsync(); } } 中的注册如下:

Startup

这完美地说明了我的问题:这里有一个services.AddScoped<ITheOtherApi, TheOtherApi>(); services.AddHttpContextAccessor(); services.AddScoped(_=> new HttpClient { BaseAddress = new Uri("https://example.org/api") }); ,我想彻底摆脱它,而不仅仅是将其移至在Startup中注册的某种工厂功能。

寻找一种获取访问令牌的同步方法,我进入了.Result的源代码,并查看可以使用intead的其他方法。我发现它实际上具有各种副作用,例如,它在执行方法名称建议的操作(从上下文中“获取令牌”)之前确实AuthenticateAsync(...)

我实际上只想要GetTokenAsync(...)中的逻辑而没有其他位,并且欢呼(!):它不是异步的......但是我无法从that method relies on AuthenticationProperties HttpContextAccessor?

我当前的解决方法(或“解决方案”?)是自己完成工作:

GetTokenValue(...)

我如何同步httpContextAccessor.HttpContext.Request.Headers .TryGetValue("Authorization", out var authorizationHeader); var bearerToken = authorizationHeader .SingleOrDefault() ?.Replace("bearer ", "", StringComparison.InvariantCultureIgnoreCase); if (string.IsNullOrWhiteSpace(bearerToken)) { throw new ArgumentException(nameof(httpContextAccessor), "HttpContextAccessor resulted in no Access Token"); } _client.SetBearerToken(token); 获取access_token,而又不用编写自己的整个标头/字符串操作帮助函数来从标头中提取它呢?

0 个答案:

没有答案