如何防止某些端点公开?

问题描述 投票:0回答:1

这里是初学者,不要生气。想象一下您正在为某个组织编写一个网站。公共网站将有前端#1,管理面板将有前端#2(他们将通过它更新该网站的内容)。

案例1

在一个解决方案中拥有 2 个独立的后端:

  1. 公共API(API)
  2. AdminApi(API)
  3. 公共服务
  4. 管理服务
  5. 数据(该数据在两个 API 之间共享,以确保两者都有实体结构的更新)

然后,您可以单独部署应用程序,限制仅来自特定网络或静态 IP 的对 AdminApi 的请求。

案例2

只有一个API,只需将[授权]到某些路线即可绕过它。问题是这足够安全吗?因为从理论上讲,您将在全球范围内公开管理面板的路由(仅对其进行一些 jwt 身份验证)。如何使这些端点在一个 API 中全局不可见?更重要的是我应该打扰吗?

你会怎么做?为什么?目标是确保应用程序安全。

附注

我的设置是:.Net 8,Nginx

.net asp.net-core security nginx
1个回答
0
投票

您能否更具体地介绍一下中间件部分?有没有我可以阅读的来源,或者你能告诉我你的意思是什么,它会是什么样子,你会用它实现什么?

当然,有多种方法可以实现这一点,中间件用于进入此应用程序的所有请求。

示例代码如下:

在appsettings.json中,您可以如下设置AdminSafeList:

{
  "AdminSafeList": "127.0.0.1;192.168.1.5;::1",
  "Logging": {

然后在中间件里面,可以参考下面的代码:

public class AdminSafeListMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<AdminSafeListMiddleware> _logger;
    private readonly byte[][] _safelist;

    public AdminSafeListMiddleware(
        RequestDelegate next,
        ILogger<AdminSafeListMiddleware> logger,
        string safelist)
    {
        var ips = safelist.Split(';');
        _safelist = new byte[ips.Length][];
        for (var i = 0; i < ips.Length; i++)
        {
            _safelist[i] = IPAddress.Parse(ips[i]).GetAddressBytes();
        }

        _next = next;
        _logger = logger;
    }

    public async Task Invoke(HttpContext context)
    {
        // here you could also check the request path by using the reuqest.path 
        if (context.Request.Method != HttpMethod.Get.Method)
        {
            var remoteIp = context.Connection.RemoteIpAddress;
            _logger.LogDebug("Request from Remote IP address: {RemoteIp}", remoteIp);

            var bytes = remoteIp.GetAddressBytes();
            var badIp = true;
            foreach (var address in _safelist)
            {
                if (address.SequenceEqual(bytes))
                {
                    badIp = false;
                    break;
                }
            }

            if (badIp)
            {
                _logger.LogWarning(
                    "Forbidden Request from Remote IP address: {RemoteIp}", remoteIp);
                context.Response.StatusCode = (int) HttpStatusCode.Forbidden;
                return;
            }
        }

        await _next.Invoke(context);
    }
}

如果您只想让它适用于特定的 MVC 控制器,您可以使用操作过滤器。

像这样:

public class ClientIpCheckActionFilter : ActionFilterAttribute
{
    private readonly ILogger _logger;
    private readonly string _safelist;

    public ClientIpCheckActionFilter(string safelist, ILogger logger)
    {
        _safelist = safelist;
        _logger = logger;
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var remoteIp = context.HttpContext.Connection.RemoteIpAddress;
        _logger.LogDebug("Remote IpAddress: {RemoteIp}", remoteIp);
        var ip = _safelist.Split(';');
        var badIp = true;
        
        if (remoteIp.IsIPv4MappedToIPv6)
        {
            remoteIp = remoteIp.MapToIPv4();
        }
        
        foreach (var address in ip)
        {
            var testIp = IPAddress.Parse(address);
            
            if (testIp.Equals(remoteIp))
            {
                badIp = false;
                break;
            }
        }

        if (badIp)
        {
            _logger.LogWarning("Forbidden Request from IP: {RemoteIp}", remoteIp);
            context.Result = new StatusCodeResult(StatusCodes.Status403Forbidden);
            return;
        }

        base.OnActionExecuting(context);
    }
}

在程序.cs内注册:

services.AddScoped<ClientIpCheckActionFilter>(container =>
{
    var loggerFactory = container.GetRequiredService<ILoggerFactory>();
    var logger = loggerFactory.CreateLogger<ClientIpCheckActionFilter>();

    return new ClientIpCheckActionFilter(
        Configuration["AdminSafeList"], logger);
});

用途:

[ServiceFilter(typeof(ClientIpCheckActionFilter))]
[HttpGet]
public IEnumerable<string> Get()

更多详情,您可以参考这篇MSFT文章

© www.soinside.com 2019 - 2024. All rights reserved.