【问题标题】:Get IP address of visitors using Flask for Python使用 Flask for Python 获取访问者的 IP 地址
【发布时间】:2011-04-15 04:05:11
【问题描述】:

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

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

【问题讨论】:

    标签: python flask ip-address werkzeug


    【解决方案1】:

    查看how to access the Request object 上的文档,然后从同一个请求对象中获取属性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。
    【解决方案2】:

    用户的IP地址可以使用如下sn-p检索:

    from flask import request
    print(request.remote_addr)
    

    【讨论】:

    • 如果应用程序在像 nginx 这样的代理服务器后面运行,则不是这样。它通常在生产中。
    【解决方案3】:

    其实你会发现,只要简单的获取以下内容,就可以得到服务器的地址:

    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,因为如果您 not 在反向代理后面,则客户端可以欺骗他们的 IP,这在许多情况都会成为安全问题。
    【解决方案4】:

    代理可能会让这有点棘手,如果您正在使用代理,请务必查看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 的方式。
    【解决方案5】:

    httpbin.org使用这种方法:

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

    【讨论】:

    • 由于代理返回127.0.0.1,不是很有帮助。
    • 谢谢,这是唯一对我有用的答案。
    【解决方案6】:

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

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

    from mod_python import apache
    
    req.get_remote_host(apache.REMOTE_NOLOOKUP)
    

    【讨论】:

      【解决方案7】:

      下面的代码总是给出客户端的公共 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
      

      【讨论】:

      【解决方案8】:

      我有 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 和你的答案,效果很好!
      【解决方案9】:

      如果您在其他平衡器后面使用 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
      

      【讨论】:

      • 注意:如果 not 在代理后面提供服务,这是不安全的。改为查看 ProxyFix。
      【解决方案10】:

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

      addr_ip4 = request.remote_addr
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-12-12
        • 1970-01-01
        • 1970-01-01
        • 2012-01-28
        • 1970-01-01
        • 2021-01-05
        • 1970-01-01
        相关资源
        最近更新 更多