繁体   English   中英

如何在节点中确定用户的IP地址

[英]How to determine a user's IP address in node

如何从 controller 中确定给定请求的 IP 地址? 例如(快递):

app.post('/get/ip/address', function (req, res) {
    // need access to IP address here
})

在您的request对象中有一个名为socket的属性,它是一个net.Socket对象。 net.Socket对象有一个属性remoteAddress ,因此您应该能够通过此调用获取 IP:

request.socket.remoteAddress

(如果您的节点版本低于 13,请使用现已弃用的request.connection.remoteAddress

编辑

正如@juand 在评论中指出的那样,如果服务器位于代理后面,则获取远程 IP 的正确方法是request.headers['x-forwarded-for']

var ip = req.headers['x-forwarded-for'] ||
     req.socket.remoteAddress ||
     null;

请注意,有时您可以在req.headers['x-forwarded-for']中获得多个 IP 地址。 此外,不会始终设置x-forwarded-for标头,这可能会引发错误。

该字段的一般格式为:

x-forwarded-for: client, proxy1, proxy2, proxy3

其中值是一个逗号+空格分隔的IP地址列表,最左边的是原始客户端,每个传递请求的连续代理添加它接收请求的IP地址。 在此示例中,请求通过proxy1proxy2proxy3 proxy3显示为请求的远程地址。

这是Arnav Gupta建议的解决方案, Martin在评论中针对未设置x-forwarded-for的情况提出了以下建议:

var ip = (req.headers['x-forwarded-for'] || '').split(',').pop().trim() || 
         req.socket.remoteAddress

使用现代 JS 的建议:

  • 仅在设置时处理x-forwarded-for ,如果是,则取第一个地址
  • 其他参数使用可选链接 (?.)
const parseIp = (req) =>
    req.headers['x-forwarded-for']?.split(',').shift()
    || req.socket?.remoteAddress

console.log(parseIp(req))
// => 127.0.0.1

如果使用快递...

req.ip

我正在查找这个然后我就像等待,我正在使用快递。 呃。

你可以保持DRY ,只使用支持IPv4IPv6的 node-ipware

安装:

npm install ipware

在您的 app.js 或中间件中:

var getIP = require('ipware')().get_ip;
app.use(function(req, res, next) {
    var ipInfo = getIP(req);
    console.log(ipInfo);
    // { clientIp: '127.0.0.1', clientIpRoutable: false }
    next();
});

它将尽最大努力获取用户的 IP 地址或返回127.0.0.1表示无法确定用户的 IP 地址。 查看README文件以了解高级选项。

您可以使用request-ip来检索用户的 IP 地址。 它处理了很多不同的边缘情况,其中一些在其他答案中提到。

披露:我创建了这个模块

安装:

npm install request-ip

在您的应用中:

var requestIp = require('request-ip');

// inside middleware handler
var ipMiddleware = function(req, res, next) {
    var clientIp = requestIp.getClientIp(req); // on localhost > 127.0.0.1
    next();
};

希望这可以帮助

request.headers['x-forwarded-for'] || request.connection.remoteAddress

如果存在x-forwarded-for标头,则使用该标头,否则使用.remoteAddress属性。

x-forwarded-for标头被添加到通过为HTTPHTTPS设置的负载平衡器(或其他类型的代理)传递的请求中(当使用代理协议TCP级别进行平衡时,也可以将此标头添加到请求中)。 这是因为request.connection.remoteAddress属性将包含负载均衡器的私有 IP 地址,而不是客户端的公共 IP 地址。 通过使用OR语句,按照上述顺序,您检查是否存在x-forwarded-for标头,如果存在则使用它,否则使用request.connection.remoteAddress

以下功能涵盖了所有案例将有所帮助

var ip;
if (req.headers['x-forwarded-for']) {
    ip = req.headers['x-forwarded-for'].split(",")[0];
} else if (req.connection && req.connection.remoteAddress) {
    ip = req.connection.remoteAddress;
} else {
    ip = req.ip;
}console.log("client IP is *********************" + ip);

警告:

不要盲目地将其用于重要的速率限制:

let ip = request.headers['x-forwarded-for'].split(',')[0];

很容易欺骗:

curl --header "X-Forwarded-For: 1.2.3.4" "https://example.com"

在这种情况下,用户的真实 IP 地址将是:

let ip = request.headers['x-forwarded-for'].split(',')[1];

我很惊讶没有其他答案提到这一点。

获取ip地址有两种方式:

  1. let ip = req.ip

  2. let ip = req.connection.remoteAddress;

但上述方法存在问题。

如果您在 Nginx 或任何代理后面运行您的应用程序,则每个 IP 地址都是127.0.0.1

因此,获取用户 IP 地址的最佳解决方案是:-

let ip = req.header('x-forwarded-for') || req.connection.remoteAddress;

 function getCallerIP(request) { var ip = request.headers['x-forwarded-for'] || request.connection.remoteAddress || request.socket.remoteAddress || request.connection.socket.remoteAddress; ip = ip.split(',')[0]; ip = ip.split(':').slice(-1); //in case the ip returned in a format: "::ffff:146.xxx.xxx.xxx" return ip; }

都试过了,还是不行

console.log(clientIp);
console.log(req.ip);

console.log(req.headers['x-forwarded-for']);
console.log(req.connection.remoteAddress);
console.log(req.socket.remoteAddress);
console.log(req.connection.socket.remoteAddress.split(",")[0]);

当我在 Nginx 代理后面运行 Express 应用程序时,您必须将应用程序变量信任代理设置为 true。 Express 提供了一些其他信任代理值,您可以在他们的文档中查看这些值,但以下步骤对我有用。

  1. app.set('trust proxy', true) 在您的 Express 应用程序中。

app.set('trust proxy', true);

  1. 在服务器块的 Nginx 配置中添加 proxy_set_header X-Forwarded-For $remote_addr。
 location / { proxy_pass http://localhost:3001; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr; # this line proxy_cache_bypass $http_upgrade; }
  1. 您现在可以从 req.header('x-forwarded-for') 或 req.connection.remoteAddress 中读取客户端的 IP 地址; ipfilter 的完整代码
module.exports = function(req, res, next) { let enable = true; // true/false let blacklist = ['xxxx']; let whitelist = ['xxxx']; let clientIp = req.header('x-forwarded-for') || req.connection.remoteAddress; if (!clientIp) { return res.json('Error'); } if (enable && paths.some((path) => (path === req.originalUrl))) { let blacklist = blacklist || []; if (blacklist.some((ip) => clientIp.match(ip) !== null)) { return res.json({ status: 401, error: 'Your IP is black-listed !'}); } let whitelist = whitelist || []; if (whitelist.length === 0 || whitelist.some((ip) => clientIp.match(ip) !== null)) { next(); return; } else { return res.json({ status: 401, error: 'Your IP is not listed !'}); } } next(); };

在节点 10.14 中,在 nginx 后面,您可以通过 nginx 标头请求它来检索 ip,如下所示:

proxy_set_header X-Real-IP $remote_addr;

然后在你的 app.js 中:

app.set('trust proxy', true);

之后,无论您希望它出现在哪里:

var userIp = req.header('X-Real-IP') || req.connection.remoteAddress;

如果您使用的是 express 版本 3.x 或更高版本,则可以使用信任代理设置 ( http://expressjs.com/api.html#trust.proxy.options.table ),它将遍历地址链x-forwarded-for 标头,并将您尚未配置为可信代理的链中的最新 ip 放入 req 对象的 ip 属性中。

如果您使用的是 express.js,那么,

app.post('/get/ip/address', function (req, res) {
      res.send(req.ip);
})

如果您获得多个 IP,这对我有用:

 var ipaddress = (req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress).split(",")[0];

在nodejs中简单获取远程ip:

var ip = req.header('x-forwarded-for') || req.connection.remoteAddress;

req.connection 自 node@12.12.0 以来已被弃用。 使用req.connection.remoteAddress获取客户端 IP 可能仍然有效,但不鼓励使用。

幸运的是, req.socket.remoteAddress从 node@0.5.10 就一直存在,是一个完美的替代品:

远程 IP 地址的字符串表示形式。 例如, '74.125.127.100''2001:4860:a005::68' 如果套接字被破坏(例如,如果客户端断开连接),则值可能undefined

 var ipaddress = (req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress).split(",")[0];

我意识到这已经被回答到死了,但这是我编写的遵循 airbnb-base eslint 标准的现代 ES6 版本。

const getIpAddressFromRequest = (request) => {
  let ipAddr = request.connection.remoteAddress;

  if (request.headers && request.headers['x-forwarded-for']) {
    [ipAddr] = request.headers['x-forwarded-for'].split(',');
  }

  return ipAddr;
};

X-Forwarded-For 标头可能包含以逗号分隔的代理 IP 列表。 顺序是 client,proxy1,proxy2,...,proxyN。 在现实世界中,人们实现了可以在此标头中提供他们想要的任何内容的代理。 如果您在负载均衡器或其他东西后面,您至少可以相信列表中的第一个 IP 至少是某个请求通过的任何代理。

这里有很多好点,但没有什么是全面的,所以这就是我最终使用的:

function getIP(req) {
  // req.connection is deprecated
  const conRemoteAddress = req.connection?.remoteAddress
  // req.socket is said to replace req.connection
  const sockRemoteAddress = req.socket?.remoteAddress
  // some platforms use x-real-ip
  const xRealIP = req.headers['x-real-ip']
  // most proxies use x-forwarded-for
  const xForwardedForIP = (() => {
    const xForwardedFor = req.headers['x-forwarded-for']
    if (xForwardedFor) {
      // The x-forwarded-for header can contain a comma-separated list of
      // IP's. Further, some are comma separated with spaces, so whitespace is trimmed.
      const ips = xForwardedFor.split(',').map(ip => ip.trim())
      return ips[0]
    }
  })()
  // prefer x-forwarded-for and fallback to the others
  return xForwardedForIP || xRealIP || sockRemoteAddress || conRemoteAddress
}

如果您使用的是 Graphql-Yoga,您可以使用以下功能:

 const getRequestIpAddress = (request) => { const requestIpAddress = request.request.headers['X-Forwarded-For'] || request.request.connection.remoteAddress if (!requestIpAddress) return null const ipv4 = new RegExp("(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)") const [ipAddress] = requestIpAddress.match(ipv4) return ipAddress }

我在 nginx 后面使用 express 和

req.headers.origin

为我做了伎俩

我将它用于 ipv4 格式

req.connection.remoteAddress.split(':').slice(-1)[0]
    const express = require('express')
    const app = express()
    const port = 3000

    app.get('/', (req, res) => {
    var ip = req.ip
    console.log(ip);
    res.send('Hello World!')
    })

   // Run as nodejs ip.js
    app.listen(port, () => {
    console.log(`Example app listening at http://localhost:${port}`)
    })

在 shell 中,您只需curl https://api.ipify.org

所以,让我们观察这个以将其移植到 node.js!

curl是一个从网站获取数据的应用程序,我们将网站“https://api.ipify.org”作为参数传递。 我们可以使用node-fetch来替换curl

我们从网站获得的数据是我们的 IP 地址,它只是获取您的 IP 的某种东西。

所以总结一下:

const fetch = require('node-fetch');

fetch('https://api.ipify.org')
  .then(response => {/* whatever */})
  .catch(err => {/* whatever */})

首先,在你的项目中安装request-ip

import requestIp from 'request-ip';
const clientIp = requestIp.getClientIp(req); 
console.log(clientIp)

如果您在 localhost 上工作,结果可能是::1 ,因为::1是真实 IP 地址并且是 localhost 的 IPV6 表示法。

您可以像这样使用 Express 获取用户 IP

请求.ip

例如在这种情况下,我们获取用户 Ip 并将其发送回用户与 req.ip

app.get('/', (req, res)=> { 
    res.send({ ip : req.ip})
    
})

Typescript中使用ValidatorJS 这是NodeJS中间件:

// Extract Client IP Address
app.use((req, res, next) => {
    let ipAddress = (req.headers['x-forwarded-for'] as string || '').split(',')[0]
    if (!validator.isIP(ipAddress))
        ipAddress = req.socket.remoteAddress?.toString().split(':').pop() || ''
    if (!validator.isIP(ipAddress))
        return res.status(400).json({errorMessage: 'Bad Request'})

    req.headers['x-forwarded-for'] = ipAddress
    next()
})

在这里,我假设所有请求都应该有一个有效的 IP 地址,因此如果没有找到有效的 IP 地址,则返回带有代码 400 的响应。

对我来说使用 kubernetes 入口(NGINX):

req.headers['x-original-forwarded-for']

在 Node.js 中像魅力一样工作

我们可以在节点 js 中检查这段代码

const os       = require('os');
const interfaces = os.networkInterfaces();

let addresses = [];

for (var k in interfaces) {

    for (var k2 in interfaces[k]) {

        const address = interfaces[k][k2];

        if ( (address.family === 'IPv4' || address.family === 'IPv6')  && 
            !address.internal) {

            addresses.push(address.address);

        }
    }
}
console.log(addresses);

use(function(req, res, next) { var ipInfo = getIP(req); console.log(ipInfo); // { clientIp: '127.0. 0.1', clientIpRoutable: false } next(); });

有同样的问题......我也是javascript新手,但我用req.connection.remoteAddress解决了这个问题; 这给了我 IP 地址(但采用 ipv6 格式 ::ffff.192.168.0.101 ),然后.slice删除前 7 个数字。

var ip = req.connection.remoteAddress;

if (ip.length < 15) 
{   
   ip = ip;
}
else
{
   var nyIP = ip.slice(7);
   ip = nyIP;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM