【问题标题】:In ASP.NET Core how do you check if request is local?在 ASP.NET Core 中如何检查请求是否是本地的?
【发布时间】:2023-03-13 16:48:01
【问题描述】:

在常规 ASP.NET 中,您可以在视图中执行此操作以确定当前请求是否来自本地主机:

HttpContext.Current.Request.IsLocal

但我在 ASP.NET 6/Core/无论它是什么意思都找不到类似的东西。

【问题讨论】:

  • 谨慎使用HttpContext.Connection.IsLocal。在我看来,HttpContext.Connection.RemoteIpAddress 的使用是更安全的方式。如果我在本地连接到测试 ASP.NET 5 RC1 项目,我会在 RemoteIpAddress 中看到 ::1,但 HttpContext.Connection.IsLocalfalse。错了。
  • 干杯奥列格,你说的对我来说也是真的。
  • 我也有同样的行为。本地总是false

标签: c# asp.net-core


【解决方案1】:

更新:ASP.NET Core 2.0 有一个名为 Url.IsLocalUrl 的方法(参见 Microsoft Docs)。

认为这段代码可以工作,但我无法完全测试它

var callingUrl = Request.Headers["Referer"].ToString();
var isLocal = Url.IsLocalUrl(callingUrl);

但请参阅下面 Will Dean 对这种方法的评论:

任何考虑使用“更新”版本来检查引荐来源标头的人都应该记住,标头非常容易被欺骗,其程度并不适用于环回 IP 地址。


原解决方案

我在寻找解决方案来了解请求是否是本地的时遇到了这个问题。不幸的是,ASP.NET 1.1.0 版在连接上没有IsLocal 方法。我在一个名为 Strathweb 的网站上找到了一个解决方案,但它也已经过时了。

我已经创建了自己的IsLocal 扩展程序,它似乎可以工作,但我不能说我已经在所有情况下都对其进行了测试,但欢迎您尝试。

public static class IsLocalExtension
{
    private const string NullIpAddress = "::1";

    public static bool IsLocal(this HttpRequest req)
    {
        var connection = req.HttpContext.Connection;
        if (connection.RemoteIpAddress.IsSet())
        {
            //We have a remote address set up
            return connection.LocalIpAddress.IsSet() 
                  //Is local is same as remote, then we are local
                ? connection.RemoteIpAddress.Equals(connection.LocalIpAddress) 
                  //else we are remote if the remote IP address is not a loopback address
                : IPAddress.IsLoopback(connection.RemoteIpAddress);
        }

        return true;
    }

    private static bool IsSet(this IPAddress address)
    {
        return address != null && address.ToString() != NullIpAddress;
    }
}

您通过使用Request 属性在控制器操作中调用它,即

 public IActionResult YourAction()
 {
     var isLocal = Request.IsLocal();
     //... your code here
 }

我希望对某人有所帮助。

【讨论】:

  • 这对我有帮助。 Here 是我的版本。
  • 任何考虑使用“更新”版本来检查 Referrer 标头的人都应该记住,标头非常容易被欺骗,在某种程度上不适用于环回 IP 地址。
  • Referer请求头与远程IP是否来自本地无关。
【解决方案2】:

在撰写本文时,.NET Core 中缺少 HttpContext.Connection.IsLocal

其他可行的解决方案仅检查第一个环回地址(::1127.0.0.1),这可能不够。

我发现以下解决方案很有用:

using Microsoft.AspNetCore.Http;
using System.Net;

namespace ApiHelpers.Filters
{
    public static class HttpContextFilters
    {
        public static bool IsLocalRequest(HttpContext context)
        {
            if (context.Connection.RemoteIpAddress.Equals(context.Connection.LocalIpAddress))
            {
                return true;
            }
            if (IPAddress.IsLoopback(context.Connection.RemoteIpAddress))
            {
                return true;
            }
            return false;
        }
    }
}

以及示例用例:

app.UseWhen(HttpContextFilters.IsLocalRequest, configuration => configuration.UseElmPage());

【讨论】:

  • 这个方法可以简化为public static bool IsLocalRequest(HttpContext context) => context.Connection.RemoteIpAddress.Equals(context.Connection.LocalIpAddress) || IPAddress.IsLoopback(context.Connection.RemoteIpAddress);
  • 第二个if不应该读if (IPAddress.IsLoopback(context.Connection.LocalIpAddress))而不是使用RemoteIpAdress吗?
  • 我认为这在实践中没有什么不同,如果有人从环回或其他方式建立到外部接口地址的连接,函数可能会返回 false,但默认情况下不会发生这种情况,所以任何无论是远程检查还是本地检查,都将选择来自 127 范围或 IPv6 的 IP 地址。此外,由于检查是关于与服务器的远程连接,因此检查远程地址更适合目的。
【解决方案3】:

以上都不适合我。

Url.IsLocalUrl 的工作方式非常不同,我觉得它有点没用:

例如,以下 URL 被视为本地:

  /Views/Default/Index.html
  ~/Index.html

以下网址是非本地的:

  ../Index.html
  http://www.contoso.com/
  http://localhost/Index.html

HttpContext.Connection.IsLocal 在 .Net Core 2.2 中不存在

比较 ControllerContext.HttpContext.Connection.RemoteIpAddressControllerContext.HttpContext.Connection.LocalIpAddress 在我的测试中也不起作用,因为远程 ip 得到“::1”,本地 ip 得到“127.0.0.1”。

最后,我用了这块:

IPAddress addr = System.Net.IPAddress.Parse( HttpContext.Connection.RemoteIpAddress.ToString() );
if (System.Net.IPAddress.IsLoopback(addr) )
{
    //do something
}

【讨论】:

    【解决方案4】:

    聚会迟到了,但如果我想在 .Net core 2.2+ 的 razor 视图中检查 IsLocal,我只需这样做:

    @if (Context.Request.Host.Value.StartsWith("localhost"))
    {
        //do local stuff
    }
    

    【讨论】:

    • 这是一种非常丑陋的做法。如果您有一个名为 localhost.site.com 的站点怎么办?甚至是 localhosting.com。
    【解决方案5】:

    ASP.NET Core 3.1 更新

    你可以用这个:

    if (Request.Host.Host == "localhost") {// do something }
    

    【讨论】:

      【解决方案6】:

      我还要提一下,将以下子句添加到您的自定义 IsLocal() 检查的末尾可能会很有用

      if (connection.RemoteIpAddress == null && connection.LocalIpAddress == null)
      {
          return true;
      }
      

      这将说明使用Microsoft.AspNetCore.TestHost 运行站点并且站点完全在内存中本地运行而没有实际 TCP/IP 连接的情况。

      【讨论】:

        【解决方案7】:

        现在

        HttpContext.Connection.IsLocal
        

        如果您需要在控制器之外检查它,那么您需要依赖 IHttpContextAccessor 来访问它。

        根据评论更新:

        HttpContext 在视图中固有地可用

        @if (Context.Connection.IsLocal)
        {
        
        }
        

        【讨论】:

        • 我通过这样做@inject IHttpContextAccessor Context; 来获取视图中的依赖关系,对吗?目前是本地的总是假的......
        • 这将在 RC2 中消失。 Filip 在这里有另一种方法:strathweb.com/2016/04/request-islocal-in-asp-net-core 但即使它似乎也严重依赖于其他中间件以及您正在使用的服务器。
        猜你喜欢
        • 1970-01-01
        • 2011-11-26
        • 2021-06-25
        • 1970-01-01
        • 1970-01-01
        • 2012-01-20
        • 2014-05-16
        相关资源
        最近更新 更多