在ASP.NET Core中使用HTTP标头传播

前言

我们常用 JWT 令牌用于身份验证,前端一般是在请求中包含 HTTP 标头 Authorization 实现。

但是,当服务间需要互相调用时,也需要"按原样"将标头传播到目标服务。

原来的解决方案是从请求中读取标头,并将其添加到对外请求标头集合中。.

后来发现,微软已经考虑了这种场景,并提供了专门的中间件来解决这个需求。

Demo

下面,我们创建 ServerA、ServiceB 两个 Web API 项目来演示这一功能。

首先,ServiceB 有一个 GET 方法,返回在请求中收到的所有标头,这使我们能够验证标头是否被传播:

[HttpGet]
public IHeaderDictionary Get()
{
    return Request.Headers;
}

执行 ServiceB 的 GET 请求,我们可以类似下图的响应:

在ASP.NET Core中使用HTTP标头传播

现在,用 ServiceA 调用 ServiceB 并返回响应。这将向我们显示哪些标头传播到 ServiceB:

[HttpGet]
public async Task<string> Get()
{
    var client = _clientFactory.CreateClient("ServiceB-Client");

    var response =  await client.GetAsync("/ServiceB");
    return await response.Content.ReadAsStringAsync();
}

执行 ServerA 的 GET 请求,可以看到,Authorization 标头并没有被传播:

在ASP.NET Core中使用HTTP标头传播

这时,我们可以引用 Nuget 包 Microsoft.AspNetCore.HeaderPropagation,并且修改 Startup.cs 启用标头传播功能:

public void ConfigureServices(IServiceCollection services)
{
    // 定义需要传播的标头
    services.AddHeaderPropagation(options => options.Headers.Add("Authorization"));
        
    services.AddHttpClient("ServiceB-Client", options => options.BaseAddress = new Uri("http://localhost:57516"))
        // 定义开启标头传播
        .AddHeaderPropagation();
    
    ......
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // 添加标头传播middleware
    app.UseHeaderPropagation();
    
    ......
}

再次执行 ServerA 的 GET 请求,可以看到,Authorization 标头被正确传播了:

在ASP.NET Core中使用HTTP标头传播

结论

标头传播中间件允许我们轻松地将标头从一个请求传播到另一个请求。

可用于下列场景:

  • 授权令牌
  • 语言选择
  • 分布式跟踪请求链
  • 浏览器信息
  • 其他自定义信息