6.15HttpContext 转发基础

HttpContext 转发是指在 ASP.NET Core 应用程序中,将一个 HTTP 请求的上下文信息(包括请求标头、请求内容、查询字符串、响应标头、响应内容等)从一个请求转发到另一个内部请求或服务的过程。这种技术允许开发者在不改变客户端请求的情况下,将请求重定向到另一个处理点,从而实现请求的代理或路由功能。

HttpContext 转发和代理 ✨#

HttpContext 转发是指在 ASP.NET Core 应用程序中,将一个 HTTP 请求的上下文信息(包括请求标头、请求内容、查询字符串、响应标头、响应内容等)从一个请求转发到另一个内部请求或服务的过程。这种技术允许开发者在不改变客户端请求的情况下,将请求重定向到另一个处理点,从而实现请求的代理或路由功能。

HttpContext 转发的应用场景:

  • API Gateway 模式:作为所有外部请求的入口点,将请求路由到正确的后端服务。
  • 负载均衡和故障转移:将请求转发到其他可用的服务实例,确保系统的稳定性和可靠性。
  • 请求日志记录和审计:将请求信息记录到日志系统或审计服务,便于监控和调试。
  • 安全过滤和验证:在转发过程中检查请求的认证信息和权限,确保请求的合法性。
  • A/B 测试和蓝绿部署:将部分流量路由到新版本的服务,逐步验证新功能。
  • 跨域请求处理:处理跨域请求,确保请求能够成功执行。

在使用 HttpContext 进行转发操作之前,请确保已完成以下两个步骤:

  1. 注册并启用 IHttpContextAccessor 服务。

Startup.csProgram.cs 文件中注册并启用 IHttpContextAccessor 服务,并配置转发目标白名单。

cs
services.AddHttpContextAccessor();  // 若使用 Furion 框架无需注入(已默认注入)// 全局配置 HttpContext 转发配置选项services.Configure<HttpContextForwardOptions>(options =>{    // 允许转发的目标主机白名单,必须显式配置;若未配置或为空,任何通过 X-Forward-To 头的转发都会被拒绝    options.AllowedHosts = ["*"];   // "*" 表示允许所有主机和协议(高风险,仅推荐在信任环境使用)});

AllowedHosts 白名单规则详解:

  • "furion.net" — 仅主机名,匹配任意协议(http/https)的默认端口(80/443)。
  • "furion.net:8080" — 主机+端口,匹配任意协议的指定端口。
  • "furion.net:*" — 主机+端口通配符,匹配任意协议下的任意端口。
  • "https://furion.net" — 协议+主机,只匹配指定协议的默认端口。
  • "http://furion.net:8080" — 协议+主机+端口,精确匹配。
  • "https://furion.net:*" — 协议+主机+端口通配符,只匹配指定协议的任意端口。
  • "[::1]"IPv6 主机(方括号包裹),匹配任意协议的默认端口。
  • "[::1]:8080"IPv6 主机+端口,匹配任意协议的指定端口。
  • "[::1]:*"IPv6 主机+端口通配符,匹配任意协议下的任意端口。
  • "http://[2001:db8::1]:8080" — 协议+IPv6 主机+端口,精确匹配。
  • "*" — 全局通配符,允许任意主机和协议(完全绕过所有主机验证)。
  1. 启用请求正文缓存中间件,以支持请求内容的重复读取。
cs
app.UseEnableBuffering();
  1. (可选) 若在转发过程中出现 The SSL connection could not be established, see inner exception. 的证书错误问题,您可以通过添加以下配置来忽略 SSL 证书验证:
cs
// 默认客户端配置services.AddHttpClient(string.Empty)    .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler    {        // 忽略 SSL 证书验证        ServerCertificateCustomValidationCallback = HttpRemoteUtility.IgnoreSslErrors,        SslProtocols = HttpRemoteUtility.AllSslProtocols    });// 若使用 SocketsHttpHandler,可以通过以下配置来忽略 SSL 证书验证services.AddHttpClient(string.Empty)    .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler()    {        SslOptions = new SslClientAuthenticationOptions        {            // 忽略 SSL 证书验证            RemoteCertificateValidationCallback = HttpRemoteUtility.IgnoreSocketSslErrors,            EnabledSslProtocols = HttpRemoteUtility.AllSslProtocols        },    });

以下是一个简单的示例,展示了如何在 ASP.NET Core 中实现 HttpContext 转发:

cs
[ApiController][Route("[controller]/[action]")]public class GetStartController(IHttpRemoteService httpRemoteService, IHttpContextAccessor httpContextAccessor) : ControllerBase{    // 转发代理到网站    [HttpGet]    [ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)] // 禁用浏览器缓存    public Task<IActionResult?> ForwardToWebSite()    {        return httpContextAccessor.HttpContext.ForwardAsResultAsync("https://github.com");    }    // 转发代理到图片    [HttpGet]    [ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)] // 禁用浏览器缓存    public Task<IActionResult?> ForwardToImage()    {        return httpContextAccessor.HttpContext.ForwardAsResultAsync(            "https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AA1u7RJI.img?w=584&h=326&m=6");    }    // 转发代理到下载    [HttpGet]    [ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)] // 禁用浏览器缓存    public Task<IActionResult?> ForwardToDownload()    {        return httpContextAccessor.HttpContext.ForwardAsResultAsync(            "https://download.visualstudio.microsoft.com/download/pr/a17b907f-8457-45a8-90db-53f2665ee49e/49bccd33593ebceb2847674fe5fd768e/aspnetcore-runtime-8.0.10-win-x64.exe");    }    // 转发代理到表单    [HttpPost]    public Task<YourRemoteFormResult?> ForwardToForm(int id, [FromForm] YourRemoteFormModel model)    {        return httpContextAccessor.HttpContext.ForwardAsAsync<YourRemoteFormResult>(            "https://localhost:7044/HttpRemote/AddForm");    }}

通过 HttpContext 转发,可以在 ASP.NET Core 应用程序中结合 Middleware 中间件技术实现灵活的请求路由和处理机制,适用于多种应用场景,如 API Gateway、负载均衡、请求日志记录、安全验证等。

HttpContextForwardBuilder 构建器#

HttpContextForwardBuilder 构建器是框架提供专门用来转换 HttpContext 请求上下文所需的各项设置。HttpContextForwardBuilder 的构造函数是私有的,因此无法直接使用 new 关键字进行实例化,不过,框架提供了 HttpContext.CreateForwardBuilder 的多个扩展重载方法创建 HttpContextForwardBuilder 的实例。

cs
httpContext.CreateForwardBuilder(httpMethod, requestUri, forwardOptions);   // forwardOptions 参数的类型为 HttpContextForwardOptionshttpContext.CreateForwardBuilder(requestUri, forwardOptions);   // 自动获取 HttpContext.Request.Method 方法进行设置

框架内部尚未提供手动构建 HttpContextForwardBuilder 并使用 Send/SendAsync 方法进行转发的功能,请改用 ForwardAsync 相关方法。

HttpContextForwardOptions 配置选项#

HttpContextForwardOptions 类型专门用于配置 HttpContext 的转发行为。您可以在项目的 Startup.csProgram.cs 文件中注册并配置该服务:

cs
// 在 HttpRemote 服务中注册services.AddHttpRemote(builder => {})    .ConfigureForwardOptions(options =>  // .ConfigureForwardOptions((options, serviceProvider) =>    {        // 在此处添加自定义配置    });// 在 services 中注册services.Configure<HttpContextForwardOptions>(options =>{    // 在此处添加自定义配置});

此外,您也可以手动创建 HttpContextForwardOptions 实例,并在进行转发时将其传入:

cs
httpContext.ForwardAsResult("https://furion.net", forwardOptions: new HttpContextForwardOptions{    // 在此处添加自定义配置});

HttpContextForwardOptions 包含以下属性:

  • 属性
    • AllowedHosts:允许转发的目标主机白名单(ICollection<string>? 类型)。
      用于防范 服务端请求伪造(SSRF 攻击。仅当目标地址的主机(含端口、协议)与列表中的某一项匹配时,转发才会被允许。
      支持的格式(匹配均忽略大小写):
      • "furion.net" – 仅主机名,匹配任意协议(http/https)的默认端口(80/443)。
      • "furion.net:8080" – 主机+端口,匹配任意协议的指定端口。
      • "furion.net:*" – 主机+端口通配符,匹配任意协议下的任意端口。
      • "https://furion.net" – 协议+主机,只匹配指定协议的默认端口。
      • "http://furion.net:8080" – 协议+主机+端口,精确匹配。
      • "https://furion.net:*" – 协议+主机+端口通配符,只匹配指定协议的任意端口。
      • "*" – 全局通配符,允许任意主机和协议(完全绕过验证,高风险)。
        若未配置或为空,所有通过 X-Forward-To 请求头指定的目标地址都将被拒绝,以防止未经授权的转发。建议尽可能使用精确规则,仅对完全可信的来源开放通配符。
    • WithQueryParameters:是否转发查询参数(URL 参数),默认值为 truebool 类型)。
    • WithRequestHeaders:是否转发请求标头,默认值为 truebool 类型)。
    • WithResponseStatusCode:是否转发响应状态码,默认值为 truebool 类型)。
    • WithResponseHeaders:是否转发响应标头,默认值为 truebool 类型)。
    • WithResponseContentHeaders:是否转发响应内容标头,默认值为 truebool 类型)。
    • ResetHostRequestHeader:是否重新设置 Host 请求标头,默认值为 falsebool 类型)。
    • IgnoreQueryParameters:忽略在转发时需要跳过的查询参数(URL 参数)列表(string[]? 类型)。
    • IgnoreRequestHeaders:忽略在转发时需要跳过的请求标头列表(string[]? 类型)。
    • IgnoreResponseHeaders:忽略在转发时需要跳过的响应标头列表(string[]? 类型)。
    • OnForward:用于在转发响应之前执行自定义操作(Action<HttpContext, HttpResponseMessage> 类型)。