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

.NET Core 5.0 API中间件如何获取请求方服务器IP及主机名

问题场景
  • 前端基于Angular 8开发,部署在IP为123.234.456.XYZ的服务器上
  • 后端为.NET Core API,部署在IP为123.234.456.PQR的独立服务器,前端应用会调用该API接口
  • 现有自定义中间件通过如下代码记录客户端IP:
IPAddress remoteIP = context.Connection.RemoteIpAddress;
  • 需求为在中间件中获取前端应用所在服务器的IP(即123.234.456.XYZ),尝试两种方案均未成功:
    1. 读取IServerVariablesFeature的REMOTE_HOST字段,仅返回API自身主机名,无法获取目标IP,实现代码如下:
    IServerVariablesFeature serverVariablesFeature = context.Features.Get<IServerVariablesFeature>();
    var hosteName = serverVariablesFeature["REMOTE_HOST"];
    Log.Debug($"Request from REMOTE_HOST: {hosteName}");
    
    1. 通过Dns.GetHostEntry解析remoteIP对应主机名,返回No such host is known报错,实现代码如下:
    string HostName= Dns.GetHostEntry(remoteIP).HostName;
    Log.Debug($"Request from HostName: {HostName}");
    
问题根因

两个方案失效的核心逻辑错误:Angular默认是客户端渲染框架,生产环境构建后是纯静态资源,运行环境是终端用户的本地浏览器,API请求是用户浏览器直接发往后端的,根本不是前端静态文件所在的123.234.456.XYZ服务器发起的。

  • context.Connection.RemoteIpAddress拿到的永远是当前发起请求的终端用户公网IP,和前端部署服务器没有任何关联。
  • IServerVariablesFeature的REMOTE_HOST字段仅在IIS托管、且开启反向DNS解析时才会返回请求源的主机名,默认配置下返回的是API服务器自身信息,完全不符合需求。
  • Dns.GetHostEntry报No such host is known是因为绝大多数普通用户的公网IP没有配置反向PTR解析记录,本来就查不到对应主机名。
正确实现方案

根据你的实际业务场景选择对应方案:

方案1:需求为校验请求来源合法性(防止接口被第三方跨域盗用)

不要尝试获取前端服务器IP,请求本身和该服务器无网络层面关联,正确实现方式:

  • 给API配置严格的CORS策略,仅允许你的前端访问源,不要使用通配符:
// Program.cs/Startup.cs中注册CORS策略
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowSpecifiedFrontend", policy =>
    {
        policy.WithOrigins("https://你的前端正式访问域名")
              .AllowAnyHeader()
              .AllowAnyMethod();
    });
});
// 中间件管道最前端启用CORS
app.UseCors("AllowSpecifiedFrontend");
  • 额外校验场景下,可以直接读取请求头的Origin或Referer字段判断来源:
// 自定义中间件中校验来源
if (!context.Request.Headers.TryGetValue("Origin", out var origin) 
    || origin != "https://你的前端正式访问域名")
{
    context.Response.StatusCode = 403;
    await context.Response.WriteAsync("Invalid request source");
    return;
}

注意:不要用IP做来源校验,前端如果接入CDN、反向代理IP会动态变化,用域名校验稳定性更高

方案2:需求为日志中记录前端部署服务器IP

该IP和HTTP请求链路无关联,需要前端构建时主动传递:

  1. Angular环境配置文件environment.prod.ts中写入前端服务器IP常量:
export const environment = {
  production: true,
  frontendServerIp: '123.234.456.XYZ',
  apiBaseUrl: 'https://123.234.456.PQR'
};
  1. 编写全局HTTP拦截器,所有发往后端的请求自动携带自定义头X-Frontend-Server-Ip:
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http';
import { environment } from 'src/environments/environment';

@Injectable()
export class AddFrontendIpInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    const modifiedReq = req.clone({
      setHeaders: { 'X-Frontend-Server-Ip': environment.frontendServerIp }
    });
    return next.handle(modifiedReq);
  }
}
  1. 后端中间件直接读取该自定义头记录日志即可:
if (context.Request.Headers.TryGetValue("X-Frontend-Server-Ip", out var frontendIp))
{
    Log.Debug($"Request static resource server IP: {frontendIp}");
}

注意:自定义请求头可以被随意伪造,仅能用于日志记录,不能作为安全校验依据

方案3:使用Angular SSR(服务端渲染)场景

只有开启Angular SSR时,页面渲染和API请求才是在前端部署服务器123.234.456.XYZ上发起的,此时:

  • 如果API服务直接暴露在公网,context.Connection.RemoteIpAddress可以直接拿到前端服务器IP
  • 如果API前端有Nginx、CDN等反向代理,需要先配置转发头中间件,放在所有其他中间件最前面:
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

配置完成后再读取context.Connection.RemoteIpAddress即可拿到真实的请求源IP(即SSR前端所在的服务器IP)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 12:36:20