如何在 ASP.NET Core 中获取用户请求的真实 IP 地址
2025-11-28 261 0
在 Web 应用中,获取访问者的真实 IP 地址是很常见的需求 —— 用于日志记录、安全、地理定位、访问控制等场景。对于 ASP.NET Core 应用来说,如果直接使用默认的方法,在没有经过任何代理或负载均衡的情况下,可以较为容易地获取用户 IP;但若部署在代理服务器(如 Nginx、负载均衡器、CDN 或反向代理)之后,就必须额外处理,才能拿到真实客户端 IP。本文将介绍 ASP.NET Core 中获取真实 IP 的正确方式,以及在代理环境下应注意的问题。
获取客户端 IP 的基础方式
在 ASP.NET Core 的控制器、Razor 页面、Middleware 或服务中,都可以通过 HttpContext.Connection.RemoteIpAddress 来获得客户端的 IP,例如:
var ip = HttpContext.Connection.RemoteIpAddress?.ToString();
这个方式在没有代理、客户端直接连接到服务器的时候通常能得到正确 IP —— 也就是发起请求的客户端 IP。
如果你的服务并不是在代理之后,就可以直接使用这个方式。
为什么在代理/负载均衡后,这种方式通常拿不到真实 IP
当你的 ASP.NET Core 应用部署在反向代理/负载均衡器后端(例如通过 Nginx、CDN 或其他代理转发请求),实际和 ASP.NET Core 建立连接的是代理服务器,而不是原始客户端。此时 RemoteIpAddress 通常会反映代理服务器的 IP,而不是用户的真实 IP。
因此,如果你仍然只依赖 RemoteIpAddress,就会得到错误或重复(每个请求都是代理 IP)——这对日志、安全等需求几乎没有意义。
使用代理转发头与中间件来获取真实 IP
为了解决代理带来的这个问题,通常的做法是:让代理(Nginx、CDN、负载均衡器等)在转发请求时,将客户端真实 IP 放入 HTTP 头中(常见的是 X-Forwarded-For,有时也用 X-Real-IP 等自定义头);然后,在 ASP.NET Core 端解析这个头,从中提取真实客户端 IP。
ASP.NET Core 提供了内置的中间件 ForwardedHeadersMiddleware 用于处理这种“转发头”。使用方式大致如下(以 minimal API 为例):
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// 启用 ForwardedHeadersMiddleware,处理 X-Forwarded-For, X-Forwarded-Proto 等头
app.UseForwardedHeaders(new ForwardedHeadersOptions {
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
// 可根据实际情况设置信任代理的 KnownProxies / KnownNetworks
// 若你信任所有代理,可以清空 KnownProxies / KnownNetworks,并不限制转发层数
ForwardLimit = null,
KnownNetworks = { },
KnownProxies = { }
});
// 后续处理中通过 HttpContext.Connection.RemoteIpAddress 获取的将是“真实客户端 IP”
在这个配置中,当请求包含适当的转发头(如 X-Forwarded-For),中间件会解析它,并将 HttpContext.Connection.RemoteIpAddress 替换为从头中得到的“最原始客户端 IP”。
如果你不使用中间件,也可以手动在代码里读取请求头,例如:
var forwarded = HttpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault();
string ip = !string.IsNullOrEmpty(forwarded)
? forwarded.Split(',')[0].Trim()
: HttpContext.Connection.RemoteIpAddress?.ToString();
其中 X-Forwarded-For 可能包含多个 IP(逗号分隔),第一个一般是客户端真实 IP。
需要注意的事项与安全考虑
-
信任代理:如果服务前面有多个代理或 CDN,不是所有转发头都可信。必须确保中间件配置中
KnownProxies或KnownNetworks包含你的代理服务器/网络,防止客户端伪造X-Forwarded-For。 -
多个代理/层级转发:当请求经过多级代理时,
X-Forwarded-For里可能包含多个 IP。应选择第一个非代理 IP 作为真实客户端 IP。 -
Fallback 机制:如果转发头不存在或格式不正确,应退回到
RemoteIpAddress,保证在非代理环境下也能工作。 -
代理配置:确保前端代理(如 Nginx、Caddy、CDN)正确设置了转发头(例如:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;),否则后端中间件无法获取真实 IP。
在各种部署环境中的兼容性
无论你的 ASP.NET Core 应用部署是在自托管、Docker 容器、Kestrel + 反向代理、CDN 加速或云托管环境(如 Azure、AWS、Docker + Nginx 等),只要确保代理正确设置转发头,且后端启用了 ForwardedHeadersMiddleware(或手动处理转发头),就可以比较安全和正确地获得真实客户端 IP。
对于只部署在“裸服务器 + Kestrel”且没有代理/负载均衡器的情况,直接使用 HttpContext.Connection.RemoteIpAddress 就足够。