簡體   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