Enhanced HttpContext.GetRemoteIpAddress() extension
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using System.Linq;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using Microsoft.AspNetCore.Antiforgery;
|
using Microsoft.AspNetCore.Antiforgery;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
@@ -13,9 +14,9 @@ namespace Microsoft.AspNetCore.Http
|
|||||||
// Search these additional headers for a remote client ip address.
|
// Search these additional headers for a remote client ip address.
|
||||||
private static readonly string[] defaultIpHeaderNames = new[]
|
private static readonly string[] defaultIpHeaderNames = new[]
|
||||||
{
|
{
|
||||||
"X-Forwarded-For", // commonly used on all known proxies
|
"Cf-Connecting-Ip", // set by Cloudflare
|
||||||
"X-Real-IP", // wide-spread alternative to X-Forwarded-For
|
"X-Real-IP", // wide-spread alternative to X-Forwarded-For
|
||||||
"CF-Connecting-IP" // set by Cloudflare
|
"X-Forwarded-For", // commonly used on all known proxies
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -37,9 +38,9 @@ namespace Microsoft.AspNetCore.Http
|
|||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Searches for additional headers in the following order:
|
/// Searches for additional headers in the following order:
|
||||||
/// <list type="number">
|
/// <list type="number">
|
||||||
/// <item>X-Forwarded-For</item>
|
/// <item>Cf-Connecting-Ip</item>
|
||||||
/// <item>X-Real-IP</item>
|
/// <item>X-Real-IP</item>
|
||||||
/// <item>CF-Connecting-IP</item>
|
/// <item>X-Forwarded-For</item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="httpContext">The current <see cref="HttpContext"/>.</param>
|
/// <param name="httpContext">The current <see cref="HttpContext"/>.</param>
|
||||||
@@ -57,7 +58,11 @@ namespace Microsoft.AspNetCore.Http
|
|||||||
if (!httpContext.Request.Headers.ContainsKey(headerName))
|
if (!httpContext.Request.Headers.ContainsKey(headerName))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
forwardedForAddress = httpContext.Request.Headers[headerName].ToString();
|
// X-Forwarded-For can contain multiple comma-separated addresses.
|
||||||
|
forwardedForAddress = httpContext.Request.Headers[headerName].ToString()
|
||||||
|
.Split(',', StringSplitOptions.TrimEntries)
|
||||||
|
.First();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,9 +78,9 @@ namespace Microsoft.AspNetCore.Http
|
|||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Searches for additional headers in the following order:
|
/// Searches for additional headers in the following order:
|
||||||
/// <list type="number">
|
/// <list type="number">
|
||||||
/// <item>X-Forwarded-For</item>
|
/// <item>Cf-Connecting-Ip</item>
|
||||||
/// <item>X-Real-IP</item>
|
/// <item>X-Real-IP</item>
|
||||||
/// <item>CF-Connecting-IP</item>
|
/// <item>X-Forwarded-For</item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="httpContext">The current <see cref="HttpContext"/>.</param>
|
/// <param name="httpContext">The current <see cref="HttpContext"/>.</param>
|
||||||
|
|||||||
@@ -18,6 +18,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
- Added `ConfigureAwait(false)` to async calls where appropriate
|
- Added `ConfigureAwait(false)` to async calls where appropriate
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Changed order of header evaluation for remote IP address parsing: `Cf-Connecting-Ip`, `X-Real-IP`, `X-Forwarded-For`
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- `GetRemoteIpAddress()` is able to get address when multiple proxies are used
|
||||||
|
|
||||||
|
|
||||||
## test/v2.1.0 - 2023-10-13
|
## test/v2.1.0 - 2023-10-13
|
||||||
|
|
||||||
|
|||||||
@@ -113,9 +113,9 @@ namespace UnitTests.AspNetCore.Extensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
[DataTestMethod]
|
[DataTestMethod]
|
||||||
[DataRow("X-Forwarded-For")]
|
[DataRow("Cf-Connecting-Ip")]
|
||||||
[DataRow("X-Real-IP")]
|
[DataRow("X-Real-IP")]
|
||||||
[DataRow("CF-Connecting-IP")]
|
[DataRow("X-Forwarded-For")]
|
||||||
public void ShouldReturnDefaultHeader(string headerName)
|
public void ShouldReturnDefaultHeader(string headerName)
|
||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
@@ -170,6 +170,24 @@ namespace UnitTests.AspNetCore.Extensions
|
|||||||
Assert.AreEqual(remote, result);
|
Assert.AreEqual(remote, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ShouldReturnFirstAddressOnMultipleProxies()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
remote = IPAddress.Parse("1.2.3.4");
|
||||||
|
var header = IPAddress.Parse("5.6.7.8");
|
||||||
|
requestHeaders.Add("X-Forwarded-For", $"{header}, 111.222.111.222");
|
||||||
|
|
||||||
|
var context = GetContext();
|
||||||
|
|
||||||
|
// act
|
||||||
|
var result = context.GetRemoteIpAddress();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
Assert.AreNotEqual(remote, result);
|
||||||
|
Assert.AreEqual(header, result);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion RemoteAddres
|
#endregion RemoteAddres
|
||||||
|
|
||||||
#region Local Request
|
#region Local Request
|
||||||
|
|||||||
Reference in New Issue
Block a user