1
0

Added White-/Blacklist Attributes, DateOnly/TimeOnly converters, TcpClientMoq

This commit is contained in:
2022-06-15 19:48:47 +02:00
parent f331be521f
commit 65bca0a922
15 changed files with 570 additions and 16 deletions

View File

@@ -0,0 +1,103 @@
using System.Linq;
using System.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace AMWD.Common.AspNetCore.Attributes
{
/// <summary>
/// Implements an IP filter. The defined addresses are blocked.
/// </summary>
public class IPBlacklistAttribute : ActionFilterAttribute
{
/// <summary>
/// Gets or sets a value indicating whether local (localhost) access is blocked (Default: false).
/// </summary>
public bool RestrictLocalAccess { get; set; }
/// <summary>
/// Gets or sets a configuration key where the blocked IP addresses are defined.
/// </summary>
/// <remarks>
/// JSON configuration example:<br/>
/// {<br/>
/// "ConfigurationKey": [<br/>
/// "10.0.0.0/8",<br/>
/// "172.16.0.0/12",<br/>
/// "fd00:123:abc::13"<br/>
/// ]<br/>
/// }
/// </remarks>
public string ConfigurationKey { get; set; }
/// <summary>
/// Gets or sets a comma separated list of blocked IP addresses.
/// </summary>
public string RestrictedIpAddresses { get; set; }
/// <inheritdoc/>
public override void OnActionExecuting(ActionExecutingContext context)
{
base.OnActionExecuting(context);
if (!RestrictLocalAccess && context.HttpContext.IsLocalRequest())
return;
var remoteIpAddress = context.HttpContext.GetRemoteIpAddress();
if (!string.IsNullOrWhiteSpace(RestrictedIpAddresses))
{
string[] ipAddresses = RestrictedIpAddresses.Split(',');
foreach (string ipAddress in ipAddresses)
{
if (string.IsNullOrWhiteSpace(ipAddress))
continue;
if (MatchesIpAddress(ipAddress, remoteIpAddress))
{
context.Result = new ForbidResult();
return;
}
}
}
var configuration = context.HttpContext.RequestServices.GetService<IConfiguration>();
if (!string.IsNullOrWhiteSpace(ConfigurationKey) && configuration != null)
{
var section = configuration.GetSection(ConfigurationKey);
if (!section.Exists())
return;
foreach (var child in section.GetChildren())
{
if (string.IsNullOrWhiteSpace(child.Value))
continue;
if (MatchesIpAddress(child.Value, remoteIpAddress))
{
context.Result = new ForbidResult();
return;
}
}
}
}
private static bool MatchesIpAddress(string configIpAddress, IPAddress remoteIpAddress)
{
if (configIpAddress.Contains('/'))
{
string[] ipNetworkParts = configIpAddress.Split('/');
var ip = IPAddress.Parse(ipNetworkParts.First());
int prefix = int.Parse(ipNetworkParts.Last());
var net = new IPNetwork(ip, prefix);
return net.Contains(remoteIpAddress);
}
return IPAddress.Parse(configIpAddress).Equals(remoteIpAddress);
}
}
}

View File

@@ -0,0 +1,102 @@
using System.Linq;
using System.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace AMWD.Common.AspNetCore.Attributes
{
/// <summary>
/// Implements an IP filter. Only defined addresses are allowed to access.
/// </summary>
public class IPWhitelistAttribute : ActionFilterAttribute
{
/// <summary>
/// Gets or sets a value indicating whether local (localhost) access is granted (Default: true).
/// </summary>
public bool AllowLocalAccess { get; set; } = true;
/// <summary>
/// Gets or sets a configuration key where the allowed IP addresses are allowed.
/// </summary>
/// <remarks>
/// JSON configuration example:<br/>
/// {<br/>
/// "ConfigurationKey": [<br/>
/// "10.0.0.0/8",<br/>
/// "172.16.0.0/12",<br/>
/// "fd00:123:abc::13"<br/>
/// ]<br/>
/// }
/// </remarks>
public string ConfigurationKey { get; set; }
/// <summary>
/// Gets or sets a comma separated list of allowed IP addresses.
/// </summary>
public string AllowedIpAddresses { get; set; }
/// <inheritdoc/>
public override void OnActionExecuting(ActionExecutingContext context)
{
base.OnActionExecuting(context);
if (AllowLocalAccess && context.HttpContext.IsLocalRequest())
return;
var remoteIpAddress = context.HttpContext.GetRemoteIpAddress();
if (!string.IsNullOrWhiteSpace(AllowedIpAddresses))
{
string[] ipAddresses = AllowedIpAddresses.Split(',');
foreach (string ipAddress in ipAddresses)
{
if (string.IsNullOrWhiteSpace(ipAddress))
continue;
if (MatchesIpAddress(ipAddress, remoteIpAddress))
return;
}
}
var configuration = context.HttpContext.RequestServices.GetService<IConfiguration>();
if (!string.IsNullOrWhiteSpace(ConfigurationKey) && configuration != null)
{
var section = configuration.GetSection(ConfigurationKey);
if (!section.Exists())
{
context.Result = new ForbidResult();
return;
}
foreach (var child in section.GetChildren())
{
if (string.IsNullOrWhiteSpace(child.Value))
continue;
if (MatchesIpAddress(child.Value, remoteIpAddress))
return;
}
}
context.Result = new ForbidResult();
}
private static bool MatchesIpAddress(string configIpAddress, IPAddress remoteIpAddress)
{
if (configIpAddress.Contains('/'))
{
string[] ipNetworkParts = configIpAddress.Split('/');
var ip = IPAddress.Parse(ipNetworkParts.First());
int prefix = int.Parse(ipNetworkParts.Last());
var net = new IPNetwork(ip, prefix);
return net.Contains(remoteIpAddress);
}
return IPAddress.Parse(configIpAddress).Equals(remoteIpAddress);
}
}
}