Dapatkan alamat IP pengunjung menggunakan Flask untuk Python

220

Saya membuat situs web di mana pengguna dapat masuk dan mengunduh file, menggunakan kerangka kerja Flask (berdasarkan Werkzeug ) yang menggunakan Python (2.6 dalam kasus saya).

Saya perlu mendapatkan alamat IP pengguna ketika mereka masuk (untuk tujuan logging). Adakah yang tahu bagaimana melakukan ini? Tentunya ada cara untuk melakukannya dengan Python?

Jon Cox
sumber

Jawaban:

295

Lihat dokumentasi tentang cara mengakses objek Permintaan dan kemudian dapatkan dari objek Permintaan yang sama ini, atributnya remote_addr.

Contoh kode

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

Untuk informasi lebih lanjut, lihat dokumentasi Werkzeug .

Tarantula
sumber
1
Beberapa kali, ini bisa berguna: request.access_route [0]
Jonathan Prates
46
Sedangkan untuk nginx, ia mengirim alamat IP asli di bawah HTTP_X_FORWARDED_FORjadi pastikan Anda tidak berakhir dengan localhost untuk setiap permintaan.
Rasty Turek
95

Proxy dapat membuat ini sedikit rumit, pastikan untuk memeriksa ProxyFix ( Flask docs ) jika Anda menggunakannya. Lihatlah request.environdi lingkungan khusus Anda. Dengan nginx saya kadang-kadang akan melakukan sesuatu seperti ini:

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

Saat proksi, seperti nginx, meneruskan alamat, mereka biasanya menyertakan IP asli di suatu tempat di header permintaan.

Perbarui Lihat implementasi flask-security . Sekali lagi, tinjau dokumentasi tentang ProxyFix sebelum menerapkan. Solusi Anda dapat bervariasi berdasarkan lingkungan khusus Anda.

Stephen Fuhry
sumber
2
Ini berfungsi ketika Anda mengatur bidang yang sesuai di konfigurasi proksi terbalik Anda. Digunakan dalam produksi.
drahnr
3
@ ahr memang benar. Kode di atas berfungsi jika dalam misalnya nginx Anda atur: proxy_set_header X-Real-IP $ remote_addr;
pors
@pors - berhasil. Saya memiliki pengaturan yang sama di conf nginx saya seperti Anda. tetapi saya masih tidak mengerti mengapa kode: request.headers.get ('X-Real-IP', request.remote_addr) tidak berfungsi. Catatan, secara intuitif saya akan mendapatkan nilai dari header dan menggunakan nama 'X-Real-IP' seperti itulah nginx conf saya.
lostdorje
82

Sebenarnya, yang akan Anda temukan adalah ketika hanya mendapatkan yang berikut ini akan memberi Anda alamat server:

request.remote_addr

Jika Anda ingin alamat IP klien, gunakan yang berikut ini:

request.environ['REMOTE_ADDR']
Chiedo
sumber
4
Hanya jika Anda berada di belakang proksi terbalik, bukan?
Ry-
3
@minitech Saya akan mengatakan bahwa kode Anda seharusnya tidak peduli apakah Anda berada di belakang proxy atau tidak. Jika opsi ini berfungsi dengan baik terlepas dari proksi terbalik dan yang lain menganggap Anda tidak berada di belakang proksi terbalik, maka ini harus lebih disukai. (Saya akan menguji ini jika saya dapat dengan mudah membuat proxy terbalik, tetapi itu akan membutuhkan lebih banyak waktu daripada yang saya miliki saat ini.)
jpmc26
@ jpmc26: Saya tidak melihat alasan mengapa itu harus bekerja sama sekali. request.remote_addrterdengar seperti properti yang harus mendapatkan alamat jarak jauh tergantung pada apakah proxy sebaliknya dipercaya.
Ry-
3
Menggunakan mod_wsgi, request.remote_addr mengembalikan alamat server setiap waktu. request.environ ['REMOTE_ADDR'] memberi saya alamat IP publik klien. Mungkin saya melewatkan sesuatu?
Chiedo
@ jpmc26 Anda sering melakukan perlu peduli jika Anda berada di belakang proxy terpencil. Jika ya, maka IP yang terhubung dengan Anda akan berasal dari server proxy jarak jauh, dan Anda harus mengandalkan header yang ditambahkannya untuk mendapatkan IP klien asli. Jika tidak , tajuk tersebut biasanya tidak ada, dan Anda ingin menggunakan IP koneksi sebagai IP klien. Dan Anda tidak bisa hanya memeriksa header dan kembali ke IP koneksi jika tidak ada, karena jika Anda tidak berada di belakang proxy terbalik, klien dapat menipu IP mereka, yang dalam banyak keadaan akan menjadi masalah keamanan .
Mark Amery
28

Alamat IP pengguna dapat diambil menggunakan cuplikan berikut:

from flask import request
print(request.remote_addr)
davidg
sumber
3
Ini tidak benar jika aplikasi berjalan di belakang server proxy seperti nginx . Yang sering di produksi.
datashaman
17

Saya memiliki Nginx dan Dengan di bawah ini 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;
        }
}

@ solusi tirtha-r bekerja untuk saya

#!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)

Permintaan dan Respons Saya:

curl -X GET http://test.api

{
    "ip": "Client Ip......"
}
Soli
sumber
13

Kode di bawah ini selalu memberikan IP publik dari klien (dan bukan IP pribadi di belakang proxy).

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
Tirtha R
sumber
Jawaban ini bersama dengan mengubah konfigurasi nginx saya sesuai dengan blog ini bekerja untuk saya. calvin.me/forward-ip-addresses-when-using-nginx-proxy
Romano Vacca
7

httpbin.org menggunakan metode ini:

return jsonify(origin=request.headers.get('X-Forwarded-For', request.remote_addr))
Pegasus
sumber
Pengembalian 127.0.0.1karena proxy, tidak terlalu membantu.
Uri Goren
3

Jika Anda menggunakan Nginx di belakang penyeimbang lainnya, misalnya Penyeimbang Aplikasi AWS, HTTP_X_FORWARDED_FOR mengembalikan daftar alamat. Bisa diperbaiki seperti itu:

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
Vlad
sumber
1

Jika Anda menggunakan lingkungan Gunicorn dan Nginx maka templat kode berikut ini berfungsi untuk Anda.

addr_ip4 = request.remote_addr
Jyotiprakash panigrahi
sumber
0

Ini harus melakukan pekerjaan. Ini memberikan alamat IP klien (host jarak jauh).

Perhatikan bahwa kode ini berjalan di sisi server.

from mod_python import apache

req.get_remote_host(apache.REMOTE_NOLOOKUP)
raviv
sumber