[英]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地址。 在此示例中,請求通過proxy1
、 proxy2
和proxy3
。 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
你可以保持DRY ,只使用支持IPv4和IPv6的 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
標頭被添加到通過為HTTP或HTTPS設置的負載平衡器(或其他類型的代理)傳遞的請求中(當使用代理協議在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地址有兩種方式:
let ip = req.ip
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 提供了一些其他信任代理值,您可以在他們的文檔中查看這些值,但以下步驟對我有用。
app.set('trust proxy', true);
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; }
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.