ead*_*dam 166 c# asp.net-core-mvc asp.net-core
你能否告诉我如何在使用MVC 6时在ASP.NET中获取客户端IP地址Request.ServerVariables["REMOTE_ADDR"]不起作用.
Dav*_*den 226
API已更新.不确定它何时改变但是根据Damien Edwards在12月底的说法,你现在可以这样做:
var remoteIpAddress = request.HttpContext.Connection.RemoteIpAddress;
Run Code Online (Sandbox Code Playgroud)
cro*_*sek 63
可以添加一些回退逻辑来处理Load Balancer的存在.
此外,通过检查,X-Forwarded-For即使没有Load Balancer(可能是因为额外的Kestrel层?),总是会设置标题:
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);
}
Run Code Online (Sandbox Code Playgroud)
假设_httpContextAccessor是通过DI提供的.
Joh*_*hna 57
在project.json中添加依赖项:
"Microsoft.AspNetCore.HttpOverrides": "1.0.0"
Run Code Online (Sandbox Code Playgroud)
在Startup.cs,Configure()方法中添加:
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor |
ForwardedHeaders.XForwardedProto
});
Run Code Online (Sandbox Code Playgroud)
而且当然:
using Microsoft.AspNetCore.HttpOverrides;
Run Code Online (Sandbox Code Playgroud)
然后,我可以使用以下方式获取IP:
Request.HttpContext.Connection.RemoteIpAddress
Run Code Online (Sandbox Code Playgroud)
在我的情况下,在VS中进行调试时我总是得到IpV6 localhost,但是当部署在IIS上时,我总是得到远程IP.
一些有用的链接: 如何在ASP.NET CORE中获取客户端IP地址?和RemoteIpAddress始终为空
该::1也许是因为:
IIS处的连接终止,然后转发到v.next Web服务器Kestrel,因此与Web服务器的连接确实来自localhost.(/sf/answers/2480968101/)
Kir*_*lla 16
您可以使用它IHttpConnectionFeature来获取此信息.
var remoteIpAddress = httpContext.GetFeature<IHttpConnectionFeature>()?.RemoteIpAddress;
Run Code Online (Sandbox Code Playgroud)
hoj*_*.mi 14
在 ASP.NET 2.1 中,在 StartUp.cs 中添加此服务:
services.AddHttpContextAccessor();
services.TryAddSingleton<IActionContextAccessor, ActionContextAccessor>();
Run Code Online (Sandbox Code Playgroud)
然后做3步:
在 MVC 控制器中定义一个变量
private IHttpContextAccessor _accessor;
Run Code Online (Sandbox Code Playgroud)DI 进入控制器的构造函数
public SomeController(IHttpContextAccessor accessor)
{
_accessor = accessor;
}
Run Code Online (Sandbox Code Playgroud)检索 IP 地址
_accessor.HttpContext.Connection.RemoteIpAddress.ToString()
Run Code Online (Sandbox Code Playgroud)这是如何完成的。
fer*_*adz 12
var remoteIpAddress = HttpContext.Features.Get<IHttpConnectionFeature>()?.RemoteIpAddress;
Run Code Online (Sandbox Code Playgroud)
rad*_*vus 12
截至 2021 年 9 月 - ASP.NET Core (5.x) MVC 项目允许我在控制器中以这种方式获取 IP 地址:
Request.HttpContext.Connection.RemoteIpAddress
Run Code Online (Sandbox Code Playgroud)
现在看起来比过去简单多了。
添加一点清晰度
我最初提到这可以在我的 HttpController 内的 MVC 项目中使用。
Request 对象可用,因为 myDataController派生自 ASP.NET MVCController类。
下面是 Microsoft 基类代码的片段,其中Request可以HttpRequest通过继承到派生自它的类来使用它。
#region Assembly Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
// Microsoft.AspNetCore.Mvc.Core.dll
#endregion
#nullable enable
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.Mvc
{
//
// Summary:
// A base class for an MVC controller without view support.
[Controller]
public abstract class ControllerBase
{
protected ControllerBase();
//
// Summary:
// Gets the Microsoft.AspNetCore.Http.HttpResponse for the executing action.
public HttpResponse Response { get; }
//
// Summary:
// Gets the Microsoft.AspNetCore.Http.HttpRequest for the executing action.
public HttpRequest Request { get; }
Run Code Online (Sandbox Code Playgroud)
Sru*_*Suk 11
我发现,你们中的一些人发现你得到的 IP 地址是 :::1 或 0.0.0.1
这是问题,因为您尝试从自己的机器获取 IP,以及尝试返回 IPv6 的 C# 的混乱。
所以,我实现了@Johna(/sf/answers/2893499101/)和@David(/sf/answers/601814601/)的答案,谢谢他们!
在这里解决:
在您的参考文献(依赖项/包)中添加 Microsoft.AspNetCore.HttpOverrides 包
在 Startup.cs 中添加这一行
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// your current code
// start code to add
// to get ip address
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
// end code to add
}
Run Code Online (Sandbox Code Playgroud)要获取 IPAddress,请在任何 Controller.cs 中使用此代码
IPAddress remoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress;
string result = "";
if (remoteIpAddress != null)
{
// If we got an IPV6 address, then we need to ask the network for the IPV4 address
// This usually only happens when the browser is on the same machine as the server.
if (remoteIpAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
{
remoteIpAddress = System.Net.Dns.GetHostEntry(remoteIpAddress).AddressList
.First(x => x.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
}
result = remoteIpAddress.ToString();
}
Run Code Online (Sandbox Code Playgroud)现在您可以从remoteIpAddress或result获取 IPv4 地址
这对我有用(DotNetCore 2.1)
[HttpGet]
public string Get()
{
var remoteIpAddress = HttpContext.Connection.RemoteIpAddress;
return remoteIpAddress.ToString();
}
Run Code Online (Sandbox Code Playgroud)
在负载均衡器后面运行.NET core(可能.NET 6/7)IIS不适用于其他建议的解决方案。
手动读取X-Forwarded-For标题即可。此代码假设标头包含一个 IP。
IPAddress ip;
var headers = Request.Headers.ToList();
if (headers.Exists((kvp) => kvp.Key == "X-Forwarded-For"))
{
// when running behind a load balancer you can expect this header
var header = headers.First((kvp) => kvp.Key == "X-Forwarded-For").Value.ToString();
// in case the IP contains a port, remove ':' and everything after
ip = IPAddress.Parse(header.Remove(header.IndexOf(':')));
}
else
{
// this will always have a value (running locally in development won't have the header)
ip = Request.HttpContext.Connection.RemoteIpAddress;
}
Run Code Online (Sandbox Code Playgroud)
编辑:感谢@JawadAlShaikh并@BozoJoe指出 IP 可以包含一个端口并且X-Forwarded-For可以包含多个 IP。
注意:使用 localhost 时,IP 地址始终为“0.0.0.1”,但是当我使用 Nginx 在 AWS EC2 实例上托管应用程序时,我收到了正确的 Ip 地址。
将以下包添加到您的项目中:
"Microsoft.AspNetCore.HttpOverrides": "2.2.0"
Run Code Online (Sandbox Code Playgroud)
然后在Startup.cs的Configure()方法中添加以下内容(确保将其放在app.UseStaticFiles()和app.UseRouting()之前)
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
// app.UseStaticFiles();
// app.UseRouting();
Run Code Online (Sandbox Code Playgroud)
然后在你的控制器类中,你可以使用以下代码获取IP地址:
IPAddress remoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress?.MapToIPv4()?.ToString();
Run Code Online (Sandbox Code Playgroud)
就我而言,我在 DigitalOcean 上运行了 DotNet Core 2.2 Web 应用程序,使用 docker 和 nginx 作为反向代理。使用 Startup.cs 中的这段代码,我可以获得客户端 IP
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.All,
RequireHeaderSymmetry = false,
ForwardLimit = null,
KnownNetworks = { new IPNetwork(IPAddress.Parse("::ffff:172.17.0.1"), 104) }
});
Run Code Online (Sandbox Code Playgroud)
::ffff:172.17.0.1 是我在使用之前获得的 ip
Request.HttpContext.Connection.RemoteIpAddress.ToString();
Run Code Online (Sandbox Code Playgroud)
根据官方文档,如果您使用Apache 或 Nginx 集成,则应将以下代码添加到Startup.ConfigureServices方法中。
// using Microsoft.AspNetCore.HttpOverrides;
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
ForwardedHeaders.XForwardedProto;
// Only loopback proxies are allowed by default.
// Clear that restriction because forwarders are enabled by explicit
// configuration.
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
});
Run Code Online (Sandbox Code Playgroud)
然后最重要的是,在Configure方法使用中
app.UseForwardedHeaders();
Run Code Online (Sandbox Code Playgroud)
进一步假设在 nginx conf 文件中的某个位置内,使用
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
Run Code Online (Sandbox Code Playgroud)
现在,第一个条目X-Forwarded-For将是真实的客户端 IP。
重要提示:如果您想保护应用程序并且不允许攻击者注入 X-Forwarded-For,请阅读此答案。
请参阅Linux 和非 IIS 反向代理的转发方案、 配置 Nginx和处理无效标头
| 归档时间: |
|
| 查看次数: |
89286 次 |
| 最近记录: |