Получите IP-адрес посетителей с помощью Flask для Python

Я создаю веб-сайт, на котором пользователи могут входить в систему и загружать файлы, используя микросхему Flask (на основе Werkzeug), который использует Python (2.6 в моем случае).

Мне нужно получить IP-адреса пользователей, когда они входят в систему (для целей регистрации). Кто-нибудь знает как это сделать? Конечно, есть способ сделать это с помощью Python?


person Jon Cox    schedule 21.09.2010    source источник


Ответы (10)


См. Документацию по как получить доступ к объекту запроса, а затем получить из тот же объект запроса, атрибут 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.

person Tarantula    schedule 21.09.2010
comment
Иногда это может быть полезно: request.access_route [0] - person Jonathan Simon Prates; 19.12.2013
comment
Что касается nginx, он отправляет реальный IP-адрес под HTTP_X_FORWARDED_FOR, поэтому убедитесь, что вы не получаете localhost для каждого запроса. - person Rasty Turek; 01.12.2014

Прокси-серверы могут сделать это немного сложнее, обязательно ознакомьтесь с ProxyFix (документы Flask) если вы его используете. Взгляните на request.environ в вашей конкретной среде. С nginx я иногда делаю что-то вроде этого:

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

Когда прокси, такие как nginx, пересылают адреса, они обычно включают исходный IP-адрес где-нибудь в заголовках запроса.

Обновление См. flask-security реализация. Опять же, перед внедрением просмотрите документацию по ProxyFix. Ваше решение может отличаться в зависимости от конкретной среды.

person Stephen Fuhry    schedule 30.10.2014
comment
Это работает, когда вы устанавливаете соответствующие поля в конфигурации вашего обратного прокси. Используется в производстве. - person drahnr; 27.02.2015
comment
@drahnr да, действительно. Приведенный выше код работает, например, если в nginx вы установили: proxy_set_header X-Real-IP $ remote_addr; - person pors; 22.09.2015
comment
@pors - работает. У меня в конфиге nginx такие же настройки, как и у вас. но я до сих пор не понимаю, почему код: request.headers.get ('X-Real-IP', request.remote_addr) не работает. Обратите внимание, что интуитивно я бы получил значение из заголовков и использовал имя «X-Real-IP», как и мой nginx conf. - person lostdorje; 21.12.2015

На самом деле вы обнаружите, что, просто получив следующее, вы получите адрес сервера:

request.remote_addr

Если вам нужен IP-адрес клиентов, используйте следующее:

request.environ['REMOTE_ADDR']
person Chiedo    schedule 30.07.2014
comment
Только если вы находитесь за обратным прокси, разве нет? - person Ry-♦; 31.07.2014
comment
@minitech Я бы сказал, что ваш код не должен заботиться о том, находитесь ли вы за прокси-сервером или нет. Если этот вариант работает надежно независимо от обратного прокси-сервера, а другой предполагает, что вы не используете обратный прокси-сервер, то это предпочтительнее. (Я бы протестировал это, если бы мог легко настроить обратный прокси, но это заняло бы больше времени, чем у меня сейчас.) - person jpmc26; 02.08.2014
comment
@ jpmc26: Я не вижу причин, почему это вообще должно работать. request.remote_addr звучит как свойство, которое должно получать удаленный адрес в зависимости от того, является ли обратный прокси-сервер доверенным. - person Ry-♦; 02.08.2014
comment
Используя mod_wsgi, request.remote_addr каждый раз возвращал адрес сервера. request.environ ['REMOTE_ADDR'] получил публичный IP-адрес клиента. Может я чего то упускаю? - person Chiedo; 04.08.2014
comment
@ jpmc26 Вы часто действительно должны заботиться о том, находитесь ли вы за удаленным прокси-сервером. Если да, то IP-адрес, с которым вы подключаетесь, будет удаленного прокси-сервера, и вам нужно будет полагаться на заголовки, которые он добавляет, чтобы получить исходный IP-адрес клиента. Если вы не, эти заголовки обычно не будут присутствовать, и вы захотите использовать IP-адрес подключения в качестве IP-адреса клиента. И вы не можете просто проверить заголовок и вернуться к IP-адресу подключения, если он отсутствует, потому что тогда, если вы не за обратным прокси-сервером, клиент может подделать свой IP-адрес, который в многие обстоятельства будут проблемой для безопасности. - person Mark Amery; 08.02.2019
comment
@MarkAmery Я имею в виду, что фреймворк должен обрабатывать эти детали за вас. Код приложения (ваш код) не должен заботиться. Сам прокси должен контролировать заголовки и заставлять их работать таким образом, чтобы спуфинг был неэффективным. - person jpmc26; 08.02.2019
comment
@ jpmc26 Фреймворк в принципе мог бы справиться с этим за вас, но только если вы явно указали ему в его конфигурации, находится ли он за обратным прокси-сервером. Кроме того, насколько мне известно, никакие фреймворки на самом деле не справляются с этим, поэтому в действительности код приложения действительно должен заботиться, даже если мы можем представить себе гипотетический мир, в котором эти вещи обрабатываются фреймворками. . Обратный прокси-сервер, возможно, не может взять на себя ответственность за обработку этого, потому что у него нет способа передать IP-адрес серверу за ним, который не может быть подделан клиентом, разговаривающим с сервером, который не за прокси. - person Mark Amery; 08.02.2019

IP-адрес пользователя можно получить с помощью следующего фрагмента:

from flask import request
print(request.remote_addr)
person davidg    schedule 12.05.2013
comment
Это неверно, если приложение работает за прокси-сервером, например nginx. Которая часто находится в производстве. - person datashaman; 13.12.2017

У меня 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......"
}
person Soli    schedule 20.08.2018

В приведенном ниже коде всегда указывается общедоступный 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
person Tirtha R    schedule 10.04.2018
comment
Этот ответ вместе с изменением моей конфигурации nginx в соответствии с этим блогом сработал для меня. calvin.me/forward-ip-addresses-when-using-nginx -прокси - person Romano Vacca; 23.06.2018

https://github.com/Runscope/httpbin использует этот метод:

return jsonify(origin=request.headers.get('X-Forwarded-For', request.remote_addr))
person Pegasus    schedule 31.07.2016
comment
Возвращает 127.0.0.1 из-за прокси, не очень полезно. - person Uri Goren; 07.07.2018

Если вы используете 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
person Vlad    schedule 06.02.2020
comment
Примечание: это небезопасно, если не обслуживается через прокси. Вместо этого попробуйте ProxyFix. - person Arel; 10.07.2020

Если вы используете среду Gunicorn и Nginx, вам подойдет следующий шаблон кода.

addr_ip4 = request.remote_addr
person Jyotiprakash panigrahi    schedule 16.02.2020

Это должно сработать. Он предоставляет IP-адрес клиента (удаленный хост).

Обратите внимание, что этот код работает на стороне сервера.

from mod_python import apache

req.get_remote_host(apache.REMOTE_NOLOOKUP)
person raviv    schedule 22.02.2018