G.D*_*mov 7 c# authentication jwt asp.net-web-api .net-framework-4.8
Web API 项目 - ASP .NET Framework 4.8
代码流程如下:
1.) 调用 API -> 它必须调用另一个 API -> 2.) 获取 JWT 身份验证令牌 -> 3.) 调用所需的方法。
问题是,如果我的 API 被调用 100 次,我将对该GetJwtToken()方法进行 100 次调用,并为所需的方法本身再进行 100 次调用,这似乎是身份验证服务器上的开销。令牌本身的寿命为 2 小时。
关于如何在另一个 Web API 中管理 Web API JWT 令牌,是否有任何记录在案的最佳实践?
我已经尝试了以下解决方案,但我仍然不确定它们是否可以被视为良好做法。
Token和ValidTo与一个静态方法GetJwtToken()的更新这些属性。在每次调用所需的外部 API 方法之前,我们检查ValidTo属性并Token通过静态方法更新值(如果它已过期)。Token。调用外部 API 方法的方法被一个try catch块包围。该 Catch(WebException ex)预计如果令牌已过期未授权的例外。我检查 HTTP 状态代码 401 - 未经授权。if (response.StatusCode == HttpStatusCode.Unauthorized)
Run Code Online (Sandbox Code Playgroud)
如果我们进入该if子句,我们Token通过调用块GetJwtToken()内的方法catch然后再次递归调用该方法来更新属性。通过这种方式,我们仅在令牌过期并引发未经授权的异常时才更新令牌。
ActionFilterAttribute使用覆盖OnActionExecuting(HttpActionContext actionContext)方法。在我们进入 Web API 控制器之前,action 属性已经检查了我们Token是否已经过期。这里的问题是我不确定在哪里保存Token财产。可能作为另一个类中的静态值。是否有其他方法可以在另一个 Web API 中管理 Web API 的 JWT 令牌,以及什么被认为是最佳实践?
一些代码片段、伪代码或文章将不胜感激。
Edit1:
我读过这个问题,但它对我没有帮助,因为它是关于如何管理前端部分的令牌。这里的项目是 Web API,它都在服务器端。
Edit2:
在这里和那里编辑了一些句子,使其更具可读性。
Edit3:
添加了一个我想到的选项。
我会以某种方式处理这个问题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;
}
}
Run Code Online (Sandbox Code Playgroud)
它将负责发出请求、响应序列化(请注意,为了简单起见,我使用了字符串响应)并处理每个请求的令牌。此外,您可能需要考虑处理错误并处理无限循环,因为它当前正在调用 self (例如,在第二次调用时,如果再次未经授权,则错误退出)。
令牌处理程序将在 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;
}
}
Run Code Online (Sandbox Code Playgroud)
这就是你消费你的方式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();
}
}
Run Code Online (Sandbox Code Playgroud)
我认为您不需要添加任何ValidTo逻辑,而只需依赖Unauthorized来自第 3 方 API 的响应,因为您只会使代码复杂化,而且无论如何您都必须处理Unauthorized响应。
唯一的问题是您可能lock会从 获取/设置令牌TokenHandler,但这只是一个基本示例,用于展示我如何实现它。
| 归档时间: |
|
| 查看次数: |
1029 次 |
| 最近记录: |