1
0
Files
common/AMWD.Common.AspNetCore/Extensions/HttpContextExtensions.cs
2023-10-17 07:32:47 +02:00

114 lines
4.1 KiB
C#

using System.Linq;
using System.Net;
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Http
{
/// <summary>
/// Extensions for the <see cref="HttpContext"/>.
/// </summary>
public static class HttpContextExtensions
{
// Search these additional headers for a remote client ip address.
private static readonly string[] defaultIpHeaderNames = new[]
{
"X-Forwarded-For", // commonly used on all known proxies
"X-Real-IP", // wide-spread alternative to X-Forwarded-For
"CF-Connecting-IP" // set by Cloudflare
};
/// <summary>
/// Retrieves the antiforgery token.
/// </summary>
/// <param name="httpContext">The current <see cref="HttpContext"/>.</param>
/// <returns>FormName, HeaderName and Value of the antiforgery token.</returns>
public static (string FormName, string HeaderName, string Value) GetAntiforgeryToken(this HttpContext httpContext)
{
var antiforgery = httpContext.RequestServices.GetService<IAntiforgery>();
var tokenSet = antiforgery?.GetAndStoreTokens(httpContext);
return (tokenSet?.FormFieldName, tokenSet?.HeaderName, tokenSet?.RequestToken);
}
/// <summary>
/// Returns the remote ip address.
/// </summary>
/// <remarks>
/// Searches for additional headers in the following order:
/// <list type="number">
/// <item>X-Forwarded-For</item>
/// <item>X-Real-IP</item>
/// <item>CF-Connecting-IP</item>
/// </list>
/// </remarks>
/// <param name="httpContext">The current <see cref="HttpContext"/>.</param>
/// <param name="ipHeaderName">The name of the header to resolve the <see cref="IPAddress"/> when behind a proxy.</param>
/// <returns>The ip address of the client.</returns>
public static IPAddress GetRemoteIpAddress(this HttpContext httpContext, string ipHeaderName = null)
{
string forwardedForAddress = null;
var headerNames = string.IsNullOrWhiteSpace(ipHeaderName)
? defaultIpHeaderNames
: new[] { ipHeaderName }.Concat(defaultIpHeaderNames);
foreach (string headerName in headerNames)
{
if (!httpContext.Request.Headers.ContainsKey(headerName))
continue;
forwardedForAddress = httpContext.Request.Headers[headerName].ToString();
break;
}
if (!string.IsNullOrWhiteSpace(forwardedForAddress) && IPAddress.TryParse(forwardedForAddress, out var remoteAddress))
return remoteAddress;
return httpContext.Connection.RemoteIpAddress;
}
/// <summary>
/// Returns whether the request was made locally.
/// </summary>
/// <remarks>
/// Searches for additional headers in the following order:
/// <list type="number">
/// <item>X-Forwarded-For</item>
/// <item>X-Real-IP</item>
/// <item>CF-Connecting-IP</item>
/// </list>
/// </remarks>
/// <param name="httpContext">The current <see cref="HttpContext"/>.</param>
/// <param name="ipHeaderName">The name of the header to resolve the <see cref="IPAddress"/> when behind a proxy.</param>
/// <returns></returns>
public static bool IsLocalRequest(this HttpContext httpContext, string ipHeaderName = null)
{
var remoteIpAddress = httpContext.GetRemoteIpAddress(ipHeaderName);
return httpContext.Connection.LocalIpAddress.Equals(remoteIpAddress);
}
/// <summary>
/// Tries to retrieve the return url.
/// </summary>
/// <param name="httpContext">The current <see cref="HttpContext"/>.</param>
/// <returns></returns>
public static string GetReturnUrl(this HttpContext httpContext)
{
if (httpContext.Items.ContainsKey("OriginalRequest"))
return httpContext.Items["OriginalRequest"].ToString();
if (httpContext.Request.Query.ContainsKey("ReturnUrl"))
return httpContext.Request.Query["ReturnUrl"].ToString();
return null;
}
/// <summary>
/// Clears a session when available.
/// </summary>
/// <param name="httpContext">The current <see cref="HttpContext"/>.</param>
public static void ClearSession(this HttpContext httpContext)
=> httpContext.Session?.Clear();
}
}