Skip to main content

5.2 HttpContext

📝 模块更新日志
  • 新特性
    •   HttpContext 获取客户端 IPv4 地址的 GetRemoteIpAddressToIPv4 方法 xff 参数 4.9.4.3 ⏱️2024.07.01 c280dfd
  • 问题修复
    •   通过 HttpContext 扩展方法 GetRemoteIpAddressToIPv4(true) 获取客户端 IP 地址出现 null 问题 4.9.8.6 ⏱️2026.01.26 8ff27e5 @boaro !934
    •   通过 HttpContext 扩展方法 GetRemoteIpAddressToIPv4(true) 获取客户端 IP 地址出现多个 IP 问题 4.9.7.246 ⏱️2026.01.14 #IDJO6T
    •   HttpRequest.GetRequestUrlAddress 扩展获取请求地址丢失端口号问题 4.9.4.5 ⏱️2024.07.11 6df5dbd
    •   启用请求 Body 重复读且在授权之前读取导致非 GET/HEAD/OPTION 请求异常 4.8.7.15 ⏱️2023.03.19 #I6NX9E

5.2.1 关于 HttpContext

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

5.2.2 获取 HttpContext

ASP.NET CoreFurion 提供了多种访问 HttpContext 的方式。

5.2.2.1 在 ControllerBase 派生类中

ControllerBase 派生类中,我们可以直接通过 HttpContext 属性获取 HttpContext 对象。

public class HomeController : Controller
{
public IActionResult Index()
{
// 在这里HttpContext 是 Controller/ControllerBase 对象的属性
var httpContext = HttpContext;

return View();
}
}

5.2.2.2 注入 IHttpContextAccessor

Furion 框架中,默认已经注册了 IHttpContextAccessor 服务,所以我们可以通过构造函数注入该接口获取。

public class AppService
{
public AppService(IHttpContextAccessor httpContextAccessor)
{
var httpContext = httpContextAccessor.HttpContext;
}
}

5.2.2.3 通过 App.HttpContext

App 静态类也提供了 App.HttpContext 获取 HttpContext 对象。

var request = App.HttpContext.Request;
非 Web 中访问

Web 完整的生命周期内,App.HttpContext 都是有效的,但在非 Web 中返回 null,避免在多线程,事件总线,定时任务等中使用。

5.2.3 HttpContext 扩展方法

Furion 框架基于 HttpContext 提供了一些常用的扩展方法。

5.2.3.1 获取当前请求的特性 Attribute

下列代码通常用于授权 Handler 中。

var attribute = httpContext.GetMetadata<SomeAttribute>();
Middleware 中间件获取特性方式

Middleware 中间件中获取有所区别,主要通过 HttpContextFeatures 获取,如:

var endpointFeature = httpContext.Features.Get<IEndpointFeature>();
var attribute = endpointFeature?.Endpoint?.Metadata?.GetMetadata<SomeAttribute>();

5.2.3.2 设置 Swagger 自动授权

Swagger 默认不能记住授权信息,一旦刷新浏览器就自动清空,所以 Furion 提供了该扩展,即使刷新浏览器也能保持授权状态。

// 检查用户登录和生成 token 代码...
// .....

// 之后调用该扩展,这样就可以实现 Swagger 刷新也能记住登录了
httpContext.SigninToSwagger("你的token");

5.2.3.3 退出 Swagger 授权

通过后端代码强制性让 Swagger 授权实现,只针对下一次请求有效!

httpContext.SignoutToSwagger();

5.2.3.4 获取本地 IP 地址

// ipv4
var ipv4 = httpContext.GetLocalIpAddressToIPv4();

// ipv6
var ipv6 = httpContext.GetLocalIpAddressToIPv6();

5.2.3.5 获取客户端 IP 地址

// ipv4
var ipv4 = httpContext.GetRemoteIpAddressToIPv4(); // Furion 4.9.4.3+ 版本支持设置 xff: true,优先获取请求头 X-Forwarded-For 转发的 IP 地址

// ipv6
var ipv6 = httpContext.GetRemoteIpAddressToIPv6();
获取不到真实 IP 处理

使用了 Nginx 反向代理后可能会出现获取不到客户端真实的 IP 地址,这时需要在 Startup.cs 中添加 IP 地址转发配置:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

// 其他代码...
}

如果添加以上配置之后获取的还是 Nginx 代理服务器的地址,那么可以尝试使用以下配置:

// 注册服务
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.All;
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
});

// 中间件(确保第一个注册)
app.UseForwardedHeaders(); // 无需参数

5.2.3.6 设置响应头 Token

httpContext.SetTokensOfResponseHeaders("token", "刷新token");

5.2.4 读取 Body 内容(重复读)

版本说明

以下内容仅限 Furion 4.7.9 + 版本使用。

默认情况下,ASP.NET Core 不支持重复读取 Body 内容,Furion 框架提供了扩展方法,需要按照以下步骤操作:

  1. Startup.csConfigure 启用 Body 重复读功能
  • .NET5 版本:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ...
app.EnableBuffering();
app.UseRouting();
// ....
}
  • .NET6+ 版本:
var builder = WebApplication.CreateBuilder(args).Inject();
// ...
var app = builder.Build();
// ...
app.UseInject();

app.EnableBuffering();
app.MapControllers();

app.Run();

注意:app.EnableBuffering() 必须在 app.UseRouting()app.MapControllers() 之前注册。

  1. 使用 HttpContextHttpRequest 扩展 .ReadBodyContentAsync() 即可
// HttpContext 扩展
var body = await httpContext.ReadBodyContentAsync();

// HttpRequest 扩展
var body = await httpContext.Request.ReadBodyContentAsync();
特别注意

如果使用了 AddJsonOptionsAddNewtonsoftJson 序列化服务,那么请确保它们在 .AddInjectXXX 之前注册。

5.2.5 反馈与建议

与我们交流

给 Furion 提 Issue