- 通用
- 身份验证
- 授权
- 数据保护
- 机密管理
ASP.NET Core 的客户端 IP 安全安全
本文介绍三种在 ASP.NET Core 应用程序中实现 IP 安全列表(也称为白名单)的方法。 你可以使用:
- 用于检查每个请求的远程 IP 地址的中间件。
- 操作筛选器来检查针对特定控制器或操作方法的请求的远程 IP 地址。
- Razor Pages 筛选器来检查 Razor 页面的请求的远程 IP 地址。
在每种情况下,包含批准的客户端 IP 地址的字符串存储在应用设置中。 中间件或筛选器会将字符串分析为一个列表,并检查远程 IP 是否在列表中。 如果不是,则返回 HTTP 403 禁止的状态代码。
安全安全
在appsettings文件中配置该列表。 它是以分号分隔的列表,并且可以包含 IPv4 和 IPv6 地址。
{ "AdminSafeList": "127.0.0.1;192.168.1.5;::1", "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Debug", "System": "Information", "Microsoft": "Information" } } }
中间件
Configure
方法将添加中间件,并在构造函数参数中将安全项的字符串传递给它。
public void Configure( IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddNLog(); app.UseStaticFiles(); app.UseMiddleware<AdminSafeListMiddleware>(Configuration["AdminSafeList"]); app.UseMvc(); }
中间件将字符串分析为数组,并在数组中查找远程 IP 地址。 如果找不到远程 IP 地址,中间件将返回 HTTP 401 禁止访问。 对于 HTTP Get 请求,将跳过此验证过程。
public class AdminSafeListMiddleware { private readonly RequestDelegate _next; private readonly ILogger<AdminSafeListMiddleware> _logger; private readonly string _adminSafeList; public AdminSafeListMiddleware( RequestDelegate next, ILogger<AdminSafeListMiddleware> logger, string adminSafeList) { _adminSafeList = adminSafeList; _next = next; _logger = logger; } public async Task Invoke(HttpContext context) { if (context.Request.Method != "GET") { var remoteIp = context.Connection.RemoteIpAddress; _logger.LogDebug("Request from Remote IP address: {RemoteIp}", remoteIp); string[] ip = _adminSafeList.Split(';'); var bytes = remoteIp.GetAddressBytes(); var badIp = true; foreach (var address in ip) { var testIp = IPAddress.Parse(address); if(testIp.GetAddressBytes().SequenceEqual(bytes)) { badIp = false; break; } } if(badIp) { _logger.LogInformation( "Forbidden Request from Remote IP address: {RemoteIp}", remoteIp); context.Response.StatusCode = 401; return; } } await _next.Invoke(context); } }
操作筛选器
如果只希望特定控制器或操作方法使用 "安全",请使用操作筛选器。 以下是一个示例:
using System.Linq; using System.Net; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Authorization; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; namespace ClientIpAspNetCore.Filters { public class ClientIpCheckFilter : ActionFilterAttribute { private readonly ILogger _logger; private readonly string _safelist; public ClientIpCheckFilter (ILoggerFactory loggerFactory, IConfiguration configuration) { _logger = loggerFactory.CreateLogger("ClientIdCheckFilter"); _safelist = configuration["AdminSafeList"]; } public override void OnActionExecuting(ActionExecutingContext context) { var remoteIp = context.HttpContext.Connection.RemoteIpAddress; _logger.LogInformation( "Remote IpAddress: {RemoteIp}", remoteIp); string[] ip = _safelist.Split(';'); var badIp = true; foreach (var address in ip) { if (remoteIp.IsIPv4MappedToIPv6) { remoteIp = remoteIp.MapToIPv4(); } var testIp = IPAddress.Parse(address); if (testIp.Equals(remoteIp)) { badIp = false; break; } } if (badIp) { _logger.LogInformation( "Forbidden Request from Remote IP address: {RemoteIp}", remoteIp); context.Result = new StatusCodeResult(401); return; } base.OnActionExecuting(context); } } }
操作筛选器将添加到服务容器中。
public void ConfigureServices(IServiceCollection services) { services.AddScoped<ClientIpCheckFilter>(); services.AddMvc(options => { options.Filters.Add (new ClientIpCheckPageFilter (_loggerFactory, Configuration)); }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
然后,可以在控制器或操作方法上使用该筛选器。
[ServiceFilter(typeof(ClientIpCheckFilter))] [HttpGet] public IEnumerable<string> Get()
在示例应用中,筛选器将应用于 Get
方法。 因此,当你通过发送 Get
API 请求来测试应用时,属性将验证客户端 IP 地址。 当你通过使用任何其他 HTTP 方法调用 API 进行测试时,中间件将验证客户端 IP。
Razor Pages 筛选器
如果需要 Razor Pages 应用的安全安全,请使用 Razor Pages 筛选器。 以下是一个示例:
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using System; using System.Linq; using System.Net; namespace ClientIpAspNetCore { public class ClientIpCheckPageFilter : IPageFilter { private readonly ILogger _logger; private readonly string _safelist; public ClientIpCheckPageFilter (ILoggerFactory loggerFactory, IConfiguration configuration) { _logger = loggerFactory.CreateLogger("ClientIdCheckPageFilter"); _safelist = configuration["AdminSafeList"]; } public void OnPageHandlerExecuting(PageHandlerExecutingContext context) { var remoteIp = context.HttpContext.Connection.RemoteIpAddress; _logger.LogInformation( "Remote IpAddress: {RemoteIp}", remoteIp); string[] ip = _safelist.Split(';'); var badIp = true; foreach (var address in ip) { if (remoteIp.IsIPv4MappedToIPv6) { remoteIp = remoteIp.MapToIPv4(); } var testIp = IPAddress.Parse(address); if (testIp.Equals(remoteIp)) { badIp = false; break; } } if (badIp) { _logger.LogInformation( "Forbidden Request from Remote IP address: {RemoteIp}", remoteIp); context.Result = new StatusCodeResult(401); return; } } public void OnPageHandlerExecuted(PageHandlerExecutedContext context) { } public void OnPageHandlerSelected(PageHandlerSelectedContext context) { } } }
此筛选器通过将其添加到 MVC 筛选器集合来启用。
public void ConfigureServices(IServiceCollection services) { services.AddScoped<ClientIpCheckFilter>(); services.AddMvc(options => { options.Filters.Add (new ClientIpCheckPageFilter (_loggerFactory, Configuration)); }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
当你运行应用并请求 Razor 页面时,Razor Pages 筛选器将验证客户端 IP。