【问题标题】:Nodejs distinguishing http requests; multiple devices with same public IPNodejs区分http请求;具有相同公共 IP 的多个设备
【发布时间】:2019-06-08 04:05:20
【问题描述】:

你好!我试图用节点表示通过 http 的客户端连接。现在我有类似的东西:

let names = [ 'john', 'margaret', 'thompson', /* ... tons more ... */ ];
let nextNameInd = 0;   

let clientsIndexedByIp = {};
let createNewClient = ip => {
  return {
    ip,
    name: names[nextNameInd++],
    numRequests: 0
  };
};

require('http').createServer((req, res) => {

  let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;

  // If this is a connection we've never seen before, create a client for it
  if (!clientsIndexedByIp.hasOwnProperty(ip)) {
    clientsIndexedByIp[ip] = createNewClient(ip);
  }

  let client = clientsIndexedByIp[ip];
  client.numRequests++;

  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify(client));

}).listen(80, '<my public ip>', 511);

我在某个远程服务器上运行此代码,它工作正常;我可以查询该服务器并获得预期的响应。但我有一个问题:我的笔记本电脑和智能手机都连接到同一个 wifi;如果我从我的笔记本电脑和智能手机查询该服务器,服务器认为这两个设备具有相同的 IP 地址,它只为它们创建一个“客户端”对象。

例如每个响应的“name”参数都是相同的。

检查我的笔记本电脑和智能手机上的 whatsmyip.org 显示相同的 IP 地址 - 这让我感到惊讶,因为我对 IP 的理解结果是错误的。在此之前,我认为所有设备都有一个唯一的 IP。

我希望不同的设备与不同的客户端相关联,即使两个设备在同一个 wifi 网络上。我假设我用来消除设备歧义的数据,仅它们的请求 IP (req.headers['x-forwarded-for'] || req.connection.remoteAddress) 是不够的。

如何区分连接到同一路由器的多个设备? req 对象中是否有一些额外的数据允许这样做?

或者只是我的笔记本电脑和智能手机具有相同的 IP 地址的网络配置错误?

谢谢!

【问题讨论】:

  • 最简单的解决方案似乎是使用cookies(每个用户的唯一cookie,也许是guid?)。当请求进入时,检查 cookie 是否存在,如果不存在,则创建一个唯一 id 并将其放置到 cookie 中并将其发送回并将其分配给您的客户端对象。
  • 这不是 Node 问题,这是“这就是 web 工作方式”的问题。您可以考虑指纹识别,而不是使用 IP。这有几个库,搜索节点指纹
  • 您刚刚发现了为什么这么多网站都有帐户注册/登录系统 :) 尝试仅在连接时从公开可用信息中识别单个设备就像试图在中间钓到一条鱼大海:你可以做到,但可能不值得努力。
  • @Molda 然后当用户清除他们的 cookie 时(对于像我这样的某些人来说,一旦他们离开网站就会发生这种情况)?然后怎样呢?如果没有登录系统,Cookie 就不能很好地衡量身份。
  • MAC地址可以帮助区分设备吗?

标签: node.js http ip-address


【解决方案1】:

如果您使用 express-fingerprint 模块,这将适用于大多数用例,例如:

const express = require('express');
const app = express();
const port = 3000;
var Fingerprint = require('express-fingerprint')

app.use(Fingerprint( { parameters:[
    Fingerprint.useragent,
    Fingerprint.geoip ]
}));

app.get('/test', function(req, res){
    console.log("Client fingerprint hash: ", req.fingerprint.hash);
    res.send("Your client Id: " + req.fingerprint.hash);
});

app.listen(port);

每个客户端都有一个唯一的哈希值,您可以使用它来识别它们。值得理解的是,这种方法会有局限性,并且在某些用例中,将 cookie 分配给客户端会更好。

【讨论】:

  • 这不是有点冒险吗?这看起来可能会混淆两个发送相同用户代理和地理信息的独立设备 - 在听起来像是一种责任的生产环境中。
  • 是的,它在生产环境中存在风险。由于哈希基于可能不唯一的属性,因此不能保证每个客户端都是唯一的。如果您确实需要为客户提供唯一身份,则需要使用另一种方法!
  • 看起来网络架构专门阻止了我想要完成的事情!我的问题的任何解决方案都只是部分解决方案,因为这是一个部分解决方案,它与任何其他答案大致一样好!我接受了。
猜你喜欢
  • 1970-01-01
  • 2012-11-07
  • 1970-01-01
  • 2015-09-16
  • 2021-12-11
  • 1970-01-01
  • 2019-01-01
  • 2020-07-15
相关资源
最近更新 更多