我的项目:
Web API 项目 - ASP .NET Framework 4.8
问题?
代码流程如下:
1.) API 被调用 -> 它必须调用另一个 API -> 2.) 获取 JWT 身份验证 token -> 3.) 调用所需的方法。
问题是如果我的 API 被调用 100 次,我将为 GetJwtToken()
调用 100 次。方法和另一个 100 用于所需方法本身,这似乎是身份验证服务器的开销。 token 本身的生命周期为 2 小时。
是否有关于如何在另一个 Web API 中管理 Web API JWT token 的最佳实践记录?
我尝试了什么?
我已经尝试了以下解决方案,但我仍然不确定它们是否可以被视为良好做法。
Token
和 ValidTo
和一种静态方法GetJwtToken()
更新这些属性。在每次调用所需的外部 API 方法之前,我们检查 ValidTo
属性并更新 Token
如果它已过期,则通过静态方法获取值。 Token
.调用外部API方法的方法用try
包围catch
block 。 Catch(WebException ex)
如果 token 已过期,则预计会出现未经授权的异常。我检查 HTTP 状态代码 401 - 未经授权。 if (response.StatusCode == HttpStatusCode.Unauthorized)
如果我们进入 if
子句我们更新 Token
属性通过调用 GetJwtToken()
catch
中的方法阻塞,然后再次递归调用该方法。通过这种方式,我们仅在 token 过期并且引发未经授权的异常时才更新 token 。ActionFilterAttribute
被覆盖 OnActionExecuting(HttpActionContext actionContext)
方法。在我们进入 Web API Controller 之前,action 属性已经检查了我们是否有 Token
。如果它已经过期。这里的问题是我不确定在哪里保存 Token
属性(property)。可能作为另一个类中的静态值。 是否有任何其他方法可以在另一个 Web API 中管理 Web API 的 JWT token ,什么被认为是最佳实践?
一些代码片段、伪代码或文章将不胜感激。
编辑1:
我已阅读 this问题,但这对我没有帮助,因为它是关于如何管理前端部分的 token 。这里的项目是 Web API,它都在服务器端。
编辑2:
在这里和那里编辑了一些句子,所以它更具可读性。
编辑3:
添加了一个我想到的选项。
最佳答案
我会用某种 BaseApiService
来处理这个问题
public class BaseApiService
{
private readonly IHttpClientFactory httpClientFactory;
private readonly ITokenHandler tokenHandler;
public BaseApiService(IHttpClientFactory httpClientFactory, ITokenHandler tokenHandler)
{
this.httpClientFactory = httpClientFactory;
this.tokenHandler = tokenHandler;
}
protected async Task<HttpResponseMessage> RequestAsync(HttpRequestMessage requestMessage)
{
var httpClient = httpClientFactory.CreateClient();
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokenHandler.Token);
var response = await httpClient.SendAsync(requestMessage);
if (!response.IsSuccessStatusCode)
{
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
var token = await tokenHandler.UpdateTokenAsync();
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
return await RequestAsync(requestMessage);
}
}
return response;
}
}
它将负责发出请求、响应序列化(注意,为了简单起见,我使用了字符串响应)和处理每个请求的 token 。此外,您可能需要考虑处理错误并处理无限循环,因为它当前正在调用 self (例如,如果再次未经授权,则在第二次调用时退出并出现错误)。token 处理程序将在 DI 中定义为单例,这是实现
public interface ITokenHandler
{
string Token { get; }
Task<string> UpdateTokenAsync();
}
public class TokenHandler : ITokenHandler
{
private readonly IHttpClientFactory httpClientFactory;
public string Token { get; private set; }
public TokenHandler(IHttpClientFactory httpClientFactory)
{
this.httpClientFactory = httpClientFactory;
}
public async Task<string> UpdateTokenAsync()
{
var httpClient = httpClientFactory.CreateClient();
var result = await httpClient.PostAsync("/external-api/token", new FormUrlEncodedContent(new []
{
new KeyValuePair<string, string>("username", "external-admin"),
new KeyValuePair<string, string>("password", "external-password"),
}));
// or handle it however you want
var token = result.IsSuccessStatusCode
? await result.Content.ReadAsStringAsync()
: null;
if (!String.IsNullOrEmpty(token))
{
Token = token;
}
return Token;
}
}
这就是您使用 BaseApiService
的方式public class TodoService : BaseApiService
{
public TodoService(IHttpClientFactory httpClientFactory, ITokenHandler tokenHandler)
: base(httpClientFactory, tokenHandler)
{
}
public async Task<string> GetTodoAsync(int id)
{
var response = await RequestAsync(new HttpRequestMessage(HttpMethod.Get, $"/todo/{id}"));
return await response.Content.ReadAsStringAsync();
}
}
我认为您不需要添加任何 ValidTo
逻辑,但只依靠你的Unauthorized
来自第 3 方 API 的响应,因为您只会使代码复杂化并且必须处理 Unauthorized
无论如何回应。唯一的问题是你可能会
lock
从 TokenHandler
获取/设置 token ,但这只是一个基本示例,展示了我将如何实现它。
关于c# - 在另一个 Web API 中管理 Web API JWT token 的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64063083/