Отримайте IP-адресу відвідувачів за допомогою Flask for Python


220

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

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

Відповіді:


295

Дивіться документацію про те, як отримати доступ до об'єкта Запит, а потім отримати з цього самого об'єкта Запит, атрибут 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 для кожного запиту.
Rasty Turek

95

Проксі-сервери можуть зробити це трохи складним, не забудьте перевірити ProxyFix ( Flask Dokcs ), якщо ви використовуєте. Погляньте на 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звучить як властивість, яка повинна отримати віддалену адресу залежно від того, чи є довірений проксі-сервер.
Ри-

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.