[英]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.