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


220

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

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

Answers:


295

请参阅有关如何访问Request对象,然后从同一Request对象(即attribute)获取文档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文档


1
有时,它可能会很有用:request.access_route [0]
Jonathan Prates 2013年

46
至于nginx,它在下发送真实的IP地址,HTTP_X_FORWARDED_FOR因此请确保您不会以每个请求的本地主机结尾。
Rasty Turek

95

代理会使这变得有些棘手,如果使用代理,请确保签出ProxyFixFlask docs)。看一下request.environ您的特定环境。使用nginx,有时我会做这样的事情:

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

当代理(例如nginx)转发地址时,它们通常在请求标头中的某处包括原始IP。

更新 请参见flask-security实现。同样,在实施之前,请阅读有关ProxyFix的文档。您的解决方案可能会因您的特定环境而异。


2
当您在反向代理的配置中设置适当的字段时,此方法有效。用于生产。
drahnr

3
@drahnr的确是。如果在例如nginx中设置,则上面的代码有效:proxy_set_header X-Real-IP $ remote_addr;
2015年

@pors-有效。我在Nginx conf中的设置与您相同。但我仍然不明白为什么代码:request.headers.get('X-Real-IP',request.remote_addr)无法正常工作。注意,直观地讲,我将从标头中获取值,并使用名称“ X-Real-IP”,因为这就是我的nginx conf的方式。
lostdorje 2015年

82

实际上,您将发现,仅获取以下内容即可获得服务器的地址:

request.remote_addr

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

request.environ['REMOTE_ADDR']

4
只有在您拥有反向代理的情况下,才不会?
Ry-

3
@minitech我要说的是,您的代码不应该关心您是否在使用代理。如果此选项可靠地工作而与反向代理无关,而另一个假定您不落后于反向代理,则应首选此选项。(如果可以轻松设置反向代理服务器,我会进行测试,但这会比现在花费更多时间。)
jpmc26 2014年

@ jpmc26:我完全没有理由。request.remote_addr听起来像一个属性,应该根据反向代理是否受信任而获得一个远程地址。
Ry-

3
使用mod_wsgi,request.remote_addr每次都返回服务器地址。request.environ ['REMOTE_ADDR']为我获取了客户端的公共IP地址。也许我缺少什么?
Chiedo 2014年

@ jpmc26你经常这样做需要关心,如果你落后远程代理。如果是,则连接到您的IP将是远程代理服务器的IP,并且您将需要依靠它添加的标头来获得原始客户端IP。如果不是,则通常不会出现这些标头,并且您将需要使用连接IP作为客户端IP。而且,您不必只检查标头并在不存在时返回到连接IP,因为如果您不在反向代理后面,则客户端可以欺骗其IP,这在很多情况下都是安全问题。 。
Mark Amery

28

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

from flask import request
print(request.remote_addr)

3
如果应用程序在像nginx这样的代理服务器后面运行,则不是这样。它经常在生产中。
datashaman

17

我有Nginx并且在Nginx Config下面:

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......"
}

13

以下代码始终提供客户端的公共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-何时使用nginx代理
Romano Vacca


3

如果您在其他平衡器(例如AWS Application Balancer)之后使用Nginx,则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

1

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

addr_ip4 = request.remote_addr

0

这应该做的工作。它提供客户端IP地址(远程主机)。

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

from mod_python import apache

req.get_remote_host(apache.REMOTE_NOLOOKUP)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.