如何结合依赖注入与JWT Token使用Refit?代码求助
问题描述
在Refit结合依赖注入使用的场景中,找不到按请求传递JWT Token的示例,且不想在Program.cs里硬编码固定Token值。现有代码调用需要授权的接口时返回401未授权,该如何正确传入JWT Token?
相关代码如下:
Program.cs
builder.Services.AddRefitClient<IMyApi>() .ConfigureHttpClient(c => { c.BaseAddress = new Uri(_appSettings.ApiBaseUrl); c.DefaultRequestHeaders.Add("Accept", "application/json"); });
Refit接口定义
public interface IMyApi { [Get("/login/")] Task<LoginResponse> Login(LoginRequest request); [Headers("Authorization: Bearer")] [Get("/MyEntity/")] Task<GetMyEntityResponse> Authenticate(GetMyEntityRequest request); }
MVC控制器代码
public class TestController : ControllerBase { private readonly IMyApi _myApiClient; public TestController(IMyApi myApiClient) { _myApiClient = myApiClient; } public async Task<IActionResult> Index() { // 登录获取JWT Token var loginResponse = await _myApiClient.Login(); var myJwtToken = loginResponse.Token; // 此处返回401未授权,如何传入JWT Token? var myEntity = await _myApiClient.GetMyEntity(); return View(myEntity); } }
解决方案
方法1:接口方法直接传Token参数(最直接)
修改Refit接口,把Token作为参数传入,利用Refit的参数绑定自动填充到请求头:
public interface IMyApi { [Get("/login/")] Task<LoginResponse> Login(LoginRequest request); // 移除固定的[Headers],改用参数绑定Authorization头 [Get("/MyEntity/")] Task<GetMyEntityResponse> Authenticate([Header("Authorization")] string authorization, GetMyEntityRequest request); }
控制器调用时,传入完整的Bearer Token字符串:
var myEntity = await _myApiClient.Authenticate($"Bearer {myJwtToken}", request);
方法2:动态获取Token自动注入(适合多请求复用)
如果想让多个请求自动复用Token,不用每次手动传参,可实现IAuthorizationHeaderGetter接口动态获取Token:
- 实现自定义的Token获取器:
public class DynamicAuthorizationHeaderGetter : IAuthorizationHeaderGetter { private readonly IHttpContextAccessor _httpContextAccessor; public DynamicAuthorizationHeaderGetter(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } public Task<string> GetAuthorizationHeaderAsync() { // 从HttpContext的Session中取已登录的Token(存储方式可根据自己业务调整) var token = _httpContextAccessor.HttpContext?.Session.GetString("JwtToken"); return Task.FromResult(token != null ? $"Bearer {token}" : null); } }
- 在
Program.cs中注册服务并配置Refit客户端:
// 注册HttpContextAccessor(未注册的话需要加) builder.Services.AddHttpContextAccessor(); // 注册自定义的Token获取器 builder.Services.AddScoped<IAuthorizationHeaderGetter, DynamicAuthorizationHeaderGetter>(); builder.Services.AddRefitClient<IMyApi>() .ConfigureHttpClient(c => { c.BaseAddress = new Uri(_appSettings.ApiBaseUrl); c.DefaultRequestHeaders.Add("Accept", "application/json"); }) // 添加授权消息处理程序 .AddHttpMessageHandler(sp => new AuthorizationMessageHandler(sp.GetRequiredService<IAuthorizationHeaderGetter>()));
- 修改Refit接口,用
[Authorize]属性替代固定的[Headers]:
public interface IMyApi { [Get("/login/")] Task<LoginResponse> Login(LoginRequest request); [Authorize] [Get("/MyEntity/")] Task<GetMyEntityResponse> Authenticate(GetMyEntityRequest request); }
- 控制器登录后把Token存入Session:
public async Task<IActionResult> Index() { var loginResponse = await _myApiClient.Login(); var myJwtToken = loginResponse.Token; // 将Token存入Session供后续请求使用 HttpContext.Session.SetString("JwtToken", myJwtToken); // 此时调用接口会自动带上Authorization头 var myEntity = await _myApiClient.GetMyEntity(); return View(myEntity); }
方法3:手动操作HttpClient请求头(临时单次请求场景)
如果只是针对某一次请求临时设置Token,可直接操作HttpClient的请求消息:
// 获取Refit客户端对应的HttpClient var httpClient = _myApiClient.GetHttpClient(); // 构造请求消息并设置Authorization头 var request = new HttpRequestMessage(HttpMethod.Get, "/MyEntity/"); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", myJwtToken); // 发送请求并反序列化结果 var response = await httpClient.SendAsync(request); response.EnsureSuccessStatusCode(); var myEntity = await response.Content.ReadFromJsonAsync<GetMyEntityResponse>();
内容的提问来源于stack exchange,提问作者user3953989
相关产品推荐
相关产品推荐

