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

如何在ViewComponent或类库中为NSwag生成的客户端添加Bearer令牌

解决方案

推荐优先使用全局统一配置方案,可同时覆盖所有使用IApiClient的场景,无需每个组件单独处理令牌:

最优方案:自定义委托处理程序自动附加令牌

通过ASP.NET Core自带的DelegatingHandler拦截HttpClient请求,统一从当前上下文中读取令牌附加到请求头,一次性解决控制器、ViewComponent、自定义服务等所有场景的令牌设置问题。

步骤1:注册HttpContext访问器

在Startup.cs的配置服务方法中添加注册:

// 开启HttpContext注入访问
services.AddHttpContextAccessor();

步骤2:实现令牌附加拦截器

新建BearerTokenHandler.cs文件:

public class BearerTokenHandler : DelegatingHandler
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public BearerTokenHandler(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // 从当前请求Cookie中读取令牌
        var token = _httpContextAccessor.HttpContext?.Request.Cookies["你存储Token的Cookie名称"];
        if (!string.IsNullOrWhiteSpace(token))
        {
            request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
        }
        return await base.SendAsync(request, cancellationToken);
    }
}

步骤3:修改HttpClient注册配置

修改Startup.cs中ApiClient的注册逻辑,将拦截器加入请求管道:

services.AddTransient<BearerTokenHandler>();
services.AddHttpClient<IApiClient, ApiClient>(client =>
{
    client.BaseAddress = new Uri(appSettings.Value.ApiBaseUrl);
})
// 附加自定义令牌拦截器
.AddHttpMessageHandler<BearerTokenHandler>();

配置完成后,原来BaseController中OnActionExecuting里的手动设置令牌逻辑可以完全删除,所有注入IApiClient的组件都会自动附加令牌。

单场景单独解决方案

如果不需要全局配置,可针对你提出的两个问题单独处理:

1. ViewComponent中设置令牌

ViewComponent的InvokeAsync/Invoke方法执行时HttpContext已经可用,直接在方法开头设置令牌即可:

public class CustomViewComponent : ViewComponent
{
    private readonly IApiClient _apiClient;

    public CustomViewComponent(IApiClient apiClient)
    {
        _apiClient = apiClient;
    }

    public async Task<IViewComponentResult> InvokeAsync()
    {
        var token = Request.Cookies["你存储Token的Cookie名称"];
        if (!string.IsNullOrWhiteSpace(token))
        {
            _apiClient.SetBearerToken(token);
        }
        // 后续业务逻辑
        return View();
    }
}

2. 控制器构造函数中实例化自定义类库的处理

控制器构造函数执行时HttpContext还未初始化,因此无法在构造函数中直接读取Cookie,有两种处理方式:

方案A:依赖注入自定义服务(推荐)

将你的IUserService也注册到依赖注入容器中,不要手动new实例,配合上面的全局令牌配置,完全不需要手动处理令牌:

// Startup.cs中注册
services.AddScoped<IUserService, UserService>();

控制器直接注入即可:

public class TestController : BaseController
{
    private readonly IUserService _userService;

    public TestController(IApiClient apiClient, IUserService userService) : base(apiClient)
    {
        _userService = userService;
    }
}

方案B:延迟实例化自定义服务

如果一定要手动实例化UserService,将实例化逻辑移到OnActionExecuting方法中执行,此时HttpContext已经初始化完成:

public class TestController : BaseController
{
    private IUserService _userService;

    public TestController(IApiClient apiClient) : base(apiClient)
    {
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        base.OnActionExecuting(context);
        // 首次执行时实例化服务
        if (_userService == null)
        {
            _userService = new UserService(ApiClient);
        }
    }
}

内容的提问来源于stack exchange,提问作者user3953989

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 08:24:09