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


222

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

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

Ответы:


297

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


1
Иногда это может быть полезно: request.access_route [0]
Джонатан Пратес

46
Что касается nginx, он отправляет реальный IP-адрес, HTTP_X_FORWARDED_FORпоэтому убедитесь, что вы не получите localhost для каждого запроса.
Расти Турек

95

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

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

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

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


2
Это работает, когда вы устанавливаете соответствующие поля в конфигурации вашего обратного прокси. Используется в производстве.
drahnr

3
@Drahnr Да, действительно. Приведенный выше код работает, если, например, в nginx вы установили: proxy_set_header X-Real-IP $ remote_addr;
Pors

@Pors - это работает. У меня те же настройки в моем Nginx Conf, что и у вас. но я все еще не понимаю, почему код: request.headers.get ('X-Real-IP', request.remote_addr) не работает. Обратите внимание, что интуитивно я получаю значение из заголовков и использую имя «X-Real-IP», так как это мой конф nginx.
lostdorje

82

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

request.remote_addr

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

request.environ['REMOTE_ADDR']

4
Только если ты за обратным прокси, нет?
Ry-

3
@minitech Я бы сказал, что ваш код не должен заботиться о том, находитесь ли вы за прокси или нет. Если этот параметр работает надежно независимо от обратного прокси-сервера, а другой предполагает, что вы не находитесь за обратным прокси-сервером, этот вариант предпочтительнее. (Я бы проверил это, если бы мог легко настроить обратный прокси-сервер, но это заняло бы больше времени, чем у меня сейчас.)
jpmc26

@ jpmc26: я не вижу причин, почему это должно работать вообще. request.remote_addrзвучит как свойство, которое должно получить удаленный адрес в зависимости от того, является ли обратный прокси доверенным.
Ry-

3
Используя mod_wsgi, request.remote_addr каждый раз возвращает адрес сервера. request.environ ['REMOTE_ADDR'] получил мне публичный IP-адрес клиента. Может я что-то упустил?
Chiedo

@ jpmc26 Вы часто делаете необходимости заботиться , если вы за удаленный прокси. Если да, то IP-адрес, который подключается к вам, будет принадлежать удаленному прокси-серверу, и вам нужно будет полагаться на добавляемые заголовки, чтобы получить исходный IP-адрес клиента. Если вы этого не сделаете , эти заголовки обычно не будут присутствовать, и вы захотите использовать IP-адрес подключения в качестве IP-адреса клиента. И вы не можете просто проверить заголовок и вернуться к IP-адресу соединения, если он отсутствует, потому что тогда, если вы не используете обратный прокси-сервер, клиент может подделать свой IP-адрес, что во многих случаях будет проблемой безопасности ,
Марк Амери

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-when-using-nginx-proxy
Романо Вакка


3

Если вы используете 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


0

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

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

from mod_python import apache

req.get_remote_host(apache.REMOTE_NOLOOKUP)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.