如何使用JavaScript检查连接是否为本地主机?

148

我希望在我的 javascript 中进行一个检查,以确定页面加载是否在我的本地机器上。

我想这样做的原因是,在开发过程中,我希望确保我的服务器端(C#)验证是否正确工作。因此,我希望能够同时显示客户端和服务器端的错误。

所以,在测试过程中,我在我的 jquery 验证中设置了一个标志,始终允许无效数据通过。这样,我就可以一次性看到客户端和服务器端的错误。

但是现在,当从开发环境切换到生产环境时,我必须手动来回更改。


6
我想提醒任何人,如果使用这些方法之一来“添加”系统功能,尤其是如果该功能可能会暴露您系统中本应安全的信息或数据,则需要特别小心。不过,使用这种技术来“删除”功能是有意义的。例如,如果您想在开发环境中抑制分析跟踪,即使在生产环境中也是如此。只需仔细考虑通过浏览器端的条件或切换所暴露的内容以及它如何可能成为安全漏洞。 - Javid Jamae
13个回答

281

location.hostname变量可以获取当前主机名。这足以让你确定你目前处于哪个环境。

if (location.hostname === "localhost" || location.hostname === "127.0.0.1")
    alert("It's a local server!");

15
有没有更通用/“万能”的解决方案,也可以覆盖使用127.0.0.1等情况? - jacobq
9
这是错误的。许多人会编辑他们的主机文件,以便找不到单词“localhost”。 - vsync
4
我同意。这是错误的。同时,在通过网络驱动器访问“本地”文件时也不起作用。 - ProblemsOfSumit
3
不确定为什么每个人都说这是错误的。这个简单的代码片段在我的本地主机和生产环境中完美运行。我的软件可以通过一行简单的代码来确定是否提供广告服务。感谢原作者。 - Andy
1
如果我在操作系统的etc/hosts文件中使用名称而不是直接使用localhost或127.0.0.1,那么这个解决方案就无法工作。 - Dee
显示剩余4条评论

47

如果在浏览器中启动静态HTML,例如从类似于file:///C:/Documents and Settings/Administrator/Desktop/的位置,检测"localhost"将不起作用。location.hostname将返回空字符串。因此,

if (location.hostname === "localhost" || location.hostname === "127.0.0.1" || location.hostname === "")
    alert("It's a local server!");

1
我遇到了这个确切的问题,虽然我自己找到了解决方案,但这个答案仍应该更高一些。 - domsson

24

这是在React中注册服务工作者时检查的方式,通过检查主机名(包括localhostIPv6)以及匹配起始位置为127来判断是否在本地主机上:

const isLocalhost = Boolean(
    window.location.hostname === 'localhost' ||
    // [::1] is the IPv6 localhost address.
    window.location.hostname === '[::1]' ||
    // 127.0.0.1/8 is considered localhost for IPv4.
    window.location.hostname.match(
        /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
    )
);

Boolean()包装器在这里扮演什么角色? - Olivier Cailloux
3
@OlivierCailloux, 可能是为了将.match()的结果限制在布尔值范围内,使用!!也可以很好地完成这个任务,而不必改变原始意思。 - VBobCat
还要注意,IPv6本地主机可以指定为[::0:1][0::0:0:1]等。 - Josh Kelley

17

这仍然不是万能的,但可能会有所改善。 现在您可以创建一个域名数组并使用.includes

const LOCAL_DOMAINS = ["localhost", "127.0.0.1", ...];

if (LOCAL_DOMAINS.includes(window.location.hostname))
  alert("It's a local server!");

1
警告:IE11不支持“.includes”。 - Danish Adeel

13
以下代码检查一个地址是否为localhost,也就是说,它是否指向从该请求发出的同一设备。
export function isLocalHost(hostname = window.location.hostname) {
  return ['localhost', '127.0.0.1', '', '::1'].includes(hostname)
}

以下代码还检查请求是否进入了本地网络。一些常见情况是本地网络IP以10.0.192.168.开头,或者以.local结尾的mDNS / Bonjour域名:
export function isLocalNetwork(hostname = window.location.hostname) {
  return (
    (['localhost', '127.0.0.1', '', '::1'].includes(hostname))
    || (hostname.startsWith('192.168.'))
    || (hostname.startsWith('10.'))
    || (hostname.endsWith('.local'))
  )
}

我不相信这是正确的?.local等并不意味着主机在本地计算机上,这就是问题所在。它们将位于本地网络上的其他设备上。 - Julian Knight
2
.local 保留给 mDNS,它专为“小型网络”设计。在大多数情况下,这是在本地网络上。请参阅 https://en.wikipedia.org/wiki/Multicast_DNS 但你说得对,问题是“连接是否为 localhost”,这只对条件的第一行成立。我会更新我的答案。谢谢! - Holtwick

12

使用与其他脚本相同的机制的最短形式:

if ( ["localhost", "127.0.0.1", ""].includes(window.location.hostname) ) {
     console.log("It's local host !");
}

1
警告:IE11不支持“.includes”。 - Danish Adeel

4
const LOCAL_DOMAINS = [ "localhost", "127.0.0.1" ];

/* offline || development */
if ( LOCAL_DOMAINS.includes(location.hostname) )
{
    BASE_URL_PUBLIC = location.hostname + "/folder/website/"; // your project folder
}

/* online || production */
else
{
    BASE_URL_PUBLIC = location.hostname;
}

3

一个简单的方法是检查主机名是否为localhost,或者检查自定义域名是否包含特定的子字符串,例如“.local” URL,如http://testsite.local

var myUrlPattern = '.local';
if (window.location.hostname === "localhost" || location.hostname === "127.0.0.1" || window.location.hostname.indexOf(myUrlPattern) >= 0) {
    alert("It's a local server!");
}

1
您可以在C#的代码后台页面中进行检测,例如:
if ((Request.Url.Host.ToLower() == "localhost"))
{
    // ..., maybe set an asp:Literal value that's in the js
}

或者如果你想从客户端脚本中实现,你可以检查 window.location.host 的值。

if (window.location.host == "localhost")
{
    // Do whatever
}

希望这能有所帮助。

3
location.host 包含主机名和端口号。请改用 location.hostname。 - pmont

0

以上答案大多数情况下都可以解决问题,但是...

  • 如果本地主机不一定是“localhost/”怎么办?
  • 如果您想在开发过程中进行前端验证怎么办?
  • 如果您想要在开发过程中实现不同的行为
    前端验证、后端验证、无验证)怎么办?

一个解决方案是设置位置哈希并检查它。

http://myname.foo.com/form.html#devValidation

你可以使用开关添加无限选项

switch(location.hash) {}
    case '#devValidation':
        // log the results and post the form
        break;
    case '#beValidation':
        // skip front end validation entirely
        break;
    case '#noValidation':
        // skip all validation $('[name=validationType']).val('novalidation');
        break;
    case '#feValidation':
    default:
        // do fe validation
        break;
}

这个解决方案仍然需要一些手动操作,并且可能会被篡改。 - A1rPun
我认为“手动工作”是微不足道的,也容易被篡改,因为我们可以在没有 JavaScript 批准的情况下提交任何我们喜欢的内容,而且大多数框架都有过滤器,在请求到达应用程序之前就可以缓解攻击。也许允许 OP 跳过服务器端验证存在风险,但这只是为了展示在哈希中使用密钥的实用性。 - Shanimal
我从不使用localhost或回环地址,因为白名单列出数十个国际化客户端(例如clientA.com、clientA.de、clientB.com、clientB.au等)将很快变成一场噩梦。我决定提供这个解决方案,因为它不关心域名,并且可以在现有网站上进行检查而无需打补丁。 - Shanimal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接