ChatGPT解决这个技术问题 Extra ChatGPT

使用 Flask for Python 获取访问者的 IP 地址

我正在创建一个用户可以登录和下载文件的网站,使用使用 Python(在我的情况下为 2.6)的 Flask micro-framework(基于 Werkzeug)。

我需要在用户登录时获取用户的 IP 地址(用于记录目的)。有谁知道如何做到这一点?当然有办法用 Python 做到这一点吗?


T
Tarantula

请参阅有关 how to access the Request object 的文档,然后从同一个 Request 对象中获取属性 remote_addr

代码示例

from flask import request
from flask import jsonify

@app.route("/get_my_ip", methods=["GET"])
def get_my_ip():
    return jsonify({'ip': request.remote_addr}), 200

有关详细信息,请参阅 Werkzeug documentation


有时,它可能很有用:request.access_route[0]
至于 nginx,它会在 HTTP_X_FORWARDED_FOR 下发送真实的 IP 地址,因此请确保您最终不会为每个请求使用 localhost。
M
Mekicha

代理可能会使这有点棘手,如果您正在使用代理,请务必查看 ProxyFix (Flask docs)。在您的特定环境中查看 request.environ。使用 nginx 我有时会做这样的事情:

from flask import request   
request.environ.get('HTTP_X_REAL_IP', request.remote_addr)   

当 nginx 等代理转发地址时,它们通常会在请求标头中的某处包含原始 IP。

更新 See the flask-security implementation。再次,在实施之前查看有关 ProxyFix 的文档。您的解决方案可能会因您的特定环境而异。


当您在反向代理的配置中设置适当的字段时,这将起作用。用于生产。
@drahnr 是的。如果在例如 nginx 中设置,则上面的代码有效: proxy_set_header X-Real-IP $remote_addr;
@pors - 它有效。我的 nginx conf 中的设置与您相同。但我仍然不明白为什么代码: request.headers.get('X-Real-IP', request.remote_addr) 不起作用。请注意,直观地我会从标头中获取值并使用名称“X-Real-IP”,因为这就是我的 nginx conf 的方式。
C
Chiedo

实际上,您会发现,当简单地获取以下内容时,您将获得服务器的地址:

request.remote_addr

如果您想要客户端 IP 地址,请使用以下命令:

request.environ['REMOTE_ADDR']

仅当您在反向代理之后,不是吗?
@minitech我会说你的代码不应该关心你是否在代理后面。如果此选项无论反向代理如何都能可靠地工作,并且另一个假设您不在反向代理后面,那么应该首选此选项。 (如果我可以轻松设置反向代理,我会对此进行测试,但这将比我目前花费的时间更多。)
@jpmc26:我看不出它为什么应该起作用。 request.remote_addr 听起来像是一个属性,它应该根据反向代理是否受信任来获取远程地址。
使用 mod_wsgi,remote_addr 每次都返回服务器地址。 request.environ['REMOTE_ADDR'] 得到了我客户端的公共 IP 地址。也许我错过了什么?
@jpmc26 你经常需要关心你是否在远程代理后面。如果是,那么连接到您的 IP 将是远程代理服务器的,您需要依赖它添加的标头来获取原始客户端 IP。如果不是,这些标头通常不会出现,并且您需要使用连接 IP 作为客户端 IP。而且您不一定只检查标头并在它不存在时回退到连接IP,因为如果您不在反向代理后面,客户端可以欺骗他们的IP,在许多情况下这将是一个安全问题.
T
Tirtha R

下面的代码总是给出客户端的公共 IP(而不是代理后面的私有 IP)。

from flask import request

if request.environ.get('HTTP_X_FORWARDED_FOR') is None:
    print(request.environ['REMOTE_ADDR'])
else:
    print(request.environ['HTTP_X_FORWARDED_FOR']) # if behind a proxy

这个答案以及根据此博客更改我的 nginx 配置对我有用。 calvin.me/forward-ip-addresses-when-using-nginx-proxy
L
Loïc

可以使用以下代码段检索用户的 IP 地址:

from flask import request
print(request.remote_addr)

如果应用程序在 nginx 之类的代理服务器后面运行,则情况并非如此。它经常在生产中。
S
Soli

我有 Nginx 和下面的 Nginx 配置:

server {
    listen 80;
    server_name xxxxxx;
    location / {
               proxy_set_header   Host                 $host;
               proxy_set_header   X-Real-IP            $remote_addr;
               proxy_set_header   X-Forwarded-For      $proxy_add_x_forwarded_for;
               proxy_set_header   X-Forwarded-Proto    $scheme;

               proxy_pass http://x.x.x.x:8000;
        }
}

@tirtha-r 解决方案对我有用

#!flask/bin/python
from flask import Flask, jsonify, request
app = Flask(__name__)

@app.route('/', methods=['GET'])
def get_tasks():
    if request.environ.get('HTTP_X_FORWARDED_FOR') is None:
        return jsonify({'ip': request.environ['REMOTE_ADDR']}), 200
    else:
        return jsonify({'ip': request.environ['HTTP_X_FORWARDED_FOR']}), 200

if __name__ == '__main__':
    app.run(debug=True,host='0.0.0.0', port=8000)

我的要求和回应:

curl -X GET http://test.api

{
    "ip": "Client Ip......"
}

我混合了@pegasus 和你的答案,效果很好!
b
bfontaine

httpbin.org 使用此方法:

return jsonify(origin=request.headers.get('X-Forwarded-For', request.remote_addr))

由于代理返回 127.0.0.1,不是很有帮助。
谢谢,这是唯一对我有用的答案。
V
Vlad

如果您在其他平衡器后面使用 Nginx,例如 AWS Application Balancer,则 HTTP_X_FORWARDED_FOR 返回地址列表。可以这样修复:

if 'X-Forwarded-For' in request.headers:
    proxy_data = request.headers['X-Forwarded-For']
    ip_list = proxy_data.split(',')
    user_ip = ip_list[0]  # first address in list is User IP
else:
    user_ip = request.remote_addr  # For local development

注意:如果不在代理后面提供,这是不安全的。改为查看 ProxyFix。
E
Elijah

这是最简单的解决方案,以及如何在生产中使用。

from flask import Flask, request
from werkzeug.middleware.proxy_fix import ProxyFix
app = Flask(__name__)
# Set environment from any X-Forwarded-For headers if proxy is configured properly
app.wsgi_app = ProxyFix(app.wsgi_app, x_host=1)

@app.before_request
def before_process():
   ip_address = request.remote_addr

include proxy_params 添加到 /etc/nginx/sites-available/$project

  location / {
    proxy_pass http://unix:$project_dir/gunicorn.sock;
    include proxy_params;
  }

include proxy_params 转发由 ProxyFix 解析的以下标头。

$ sudo cat /etc/nginx/proxy_params 
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

J
Jyotiprakash panigrahi

如果您使用的是 Gunicorn 和 Nginx 环境,那么以下代码模板适合您。

addr_ip4 = request.remote_addr

T
Tetsuya Yamamoto

这应该可以完成这项工作。它提供客户端 IP 地址(远程主机)。

请注意,此代码在服务器端运行。

from mod_python import apache

req.get_remote_host(apache.REMOTE_NOLOOKUP)

M
MattiH

我没有使用 Google Cloud App Engine 完成上述任何工作。然而,这行得通

ip = request.headers['X-Appengine-User-Ip']

建议的 request.remote_addr 每次只返回本地主机 IP。