咨询区
eadam:
在 ASP.NET 中我可以用 Request.ServerVariables["REMOTE_ADDR"]
来获取客户端IP地址,请问在 ASP.NET Core 中我该如何实现呢?
回答区
CodingYourLife
如果你用的是 .NET 5
,可以用内部提供的扩展方法来实现获取客户端IP,参考代码如下:
public static class HttpContextExtensions
{//https://gist.github.com/jjxtra/3b240b31a1ed3ad783a7dcdb6df12c36public static IPAddress GetRemoteIPAddress(this HttpContext context, bool allowForwarded = true){if (allowForwarded){string header = (context.Request.Headers["CF-Connecting-IP"].FirstOrDefault() ?? context.Request.Headers["X-Forwarded-For"].FirstOrDefault());if (IPAddress.TryParse(header, out IPAddress ip)){return ip;}}return context.Connection.RemoteIpAddress;}
}
然后像下面这样调用。
var ipFromExtensionMethod = HttpContext.GetRemoteIPAddress().ToString();
crokusek:
在 ASP.NET Core 的世界里,一般都会在 Kestrel 前加上 IIS 或 Nginx 做负载均衡,在这种场景下获取客户端IP需要做一些额外处理,那就是在 Http Header 头上增加 X-Forwarded-For
标记,其实不管有没有负载均衡,建议都加上,参考代码如下:
public string GetRequestIP(bool tryUseXForwardHeader = true)
{string ip = null;// todo support new "Forwarded" header (2014) https://en.wikipedia.org/wiki/X-Forwarded-For// X-Forwarded-For (csv list): Using the First entry in the list seems to work// for 99% of cases however it has been suggested that a better (although tedious)// approach might be to read each IP from right to left and use the first public IP.// http://stackoverflow.com/a/43554000/538763//if (tryUseXForwardHeader)ip = GetHeaderValueAs<string>("X-Forwarded-For").SplitCsv().FirstOrDefault();// RemoteIpAddress is always null in DNX RC1 Update1 (bug).if (ip.IsNullOrWhitespace() && _httpContextAccessor.HttpContext?.Connection?.RemoteIpAddress != null)ip = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();if (ip.IsNullOrWhitespace())ip = GetHeaderValueAs<string>("REMOTE_ADDR");// _httpContextAccessor.HttpContext?.Request?.Host this is the local host.if (ip.IsNullOrWhitespace())throw new Exception("Unable to determine caller's IP.");return ip;
}public T GetHeaderValueAs<T>(string headerName)
{StringValues values;if (_httpContextAccessor.HttpContext?.Request?.Headers?.TryGetValue(headerName, out values) ?? false){string rawValues = values.ToString(); // writes out as Csv when there are multiple.if (!rawValues.IsNullOrWhitespace())return (T)Convert.ChangeType(values.ToString(), typeof(T));}return default(T);
}public static List<string> SplitCsv(this string csvList, bool nullOrWhitespaceInputReturnsNull = false)
{if (string.IsNullOrWhiteSpace(csvList))return nullOrWhitespaceInputReturnsNull ? null : new List<string>();return csvList.TrimEnd(',').Split(',').AsEnumerable<string>().Select(s => s.Trim()).ToList();
}public static bool IsNullOrWhitespace(this string s)
{return String.IsNullOrWhiteSpace(s);
}
点评区
确实在获取客户端IP的时候要考虑到 X-Forwarded-For
,毕竟对外的业务系统都是按集群为单位对外提供服务的,学习了。