You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何结合依赖注入与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:

  1. 实现自定义的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);
    }
}
  1. 在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>()));
  1. 修改Refit接口,用[Authorize]属性替代固定的[Headers]:
public interface IMyApi
{
    [Get("/login/")]
    Task<LoginResponse> Login(LoginRequest request);

    [Authorize]
    [Get("/MyEntity/")]
    Task<GetMyEntityResponse> Authenticate(GetMyEntityRequest request);
}
  1. 控制器登录后把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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 02:48:10