Nhận địa chỉ IP của khách truy cập bằng Flask cho Python


220

Tôi đang tạo một trang web nơi người dùng có thể đăng nhập và tải xuống các tệp, sử dụng khung vi mô Flask (dựa trên Werkzeug ) sử dụng Python (2.6 trong trường hợp của tôi).

Tôi cần lấy địa chỉ IP của người dùng khi họ đăng nhập (cho mục đích đăng nhập). Có ai biết cách để làm điều này không? Chắc chắn có một cách để làm điều đó với Python?

Câu trả lời:


295

Xem tài liệu về cách truy cập đối tượng Yêu cầu và sau đó nhận từ cùng một đối tượng Yêu cầu, thuộc tính remote_addr.

Mã ví dụ

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

Để biết thêm thông tin, xem tài liệu Werkzeug .


1
Đôi khi, nó có thể hữu ích: request.access_route [0]
Jonathan Prates 19/12/13

46
Đối với nginx, nó sẽ gửi địa chỉ IP thực bên dưới HTTP_X_FORWARDED_FORđể đảm bảo bạn không kết thúc với localhost cho mỗi yêu cầu.
Rure Turek

95

Proxy có thể làm cho điều này một chút khó khăn, hãy đảm bảo kiểm tra ProxyFix ( tài liệu Flask ) nếu bạn đang sử dụng. Hãy nhìn vào request.environtrong môi trường cụ thể của bạn. Với nginx đôi khi tôi sẽ làm một cái gì đó như thế này:

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

Khi proxy, chẳng hạn như nginx, chuyển tiếp địa chỉ, chúng thường bao gồm IP gốc ở đâu đó trong tiêu đề yêu cầu.

Cập nhật Xem thực hiện bảo mật bình . Một lần nữa, xem lại tài liệu về ProxyFix trước khi thực hiện. Giải pháp của bạn có thể thay đổi dựa trên môi trường cụ thể của bạn.


2
Điều này hoạt động khi bạn đặt các trường thích hợp trong cấu hình proxy ngược của bạn. Được sử dụng trong sản xuất.
drahnr

3
@drahnr đúng vậy. Đoạn mã trên hoạt động nếu trong ví dụ nginx bạn đặt: proxy_set_header X-Real-IP $ remote_addr;
pors

@pors - nó hoạt động. tôi có cùng cài đặt trong nginx conf của tôi như bạn. nhưng tôi vẫn không hiểu tại sao mã: request.headers.get ('X-Real-IP', request.remote_addr) không hoạt động. Lưu ý, theo trực giác tôi sẽ nhận được giá trị từ các tiêu đề và sử dụng tên 'X-Real-IP' như cách mà nginx conf của tôi là.
mấtdorje

82

Trên thực tế, những gì bạn sẽ tìm thấy là khi chỉ cần nhận được những điều sau đây sẽ giúp bạn có được địa chỉ của máy chủ:

request.remote_addr

Nếu bạn muốn địa chỉ IP của khách hàng, thì hãy sử dụng như sau:

request.environ['REMOTE_ADDR']

4
Chỉ khi bạn đứng sau một proxy ngược, không?
Ry-

3
@minitech Tôi sẽ nói rằng mã của bạn không nên quan tâm liệu bạn có đứng sau proxy hay không. Nếu tùy chọn này hoạt động đáng tin cậy bất kể proxy ngược và các giả định khác cho rằng bạn không đứng sau proxy ngược, thì nên sử dụng tùy chọn này. (Tôi sẽ kiểm tra điều này nếu tôi có thể dễ dàng thiết lập proxy ngược, nhưng việc này sẽ mất nhiều thời gian hơn tôi có vào lúc này.)
jpmc26

@ jpmc26: Tôi thấy không có lý do tại sao nó nên hoạt động cả. request.remote_addrÂm thanh giống như một tài sản sẽ nhận được một địa chỉ từ xa tùy thuộc vào việc proxy ngược có đáng tin cậy hay không.
Ry-

3
Sử dụng mod_wsgi, request.remote_addr trả về địa chỉ máy chủ mỗi lần. request.envir ['REMOTE_ADDR'] đã cho tôi địa chỉ IP công khai của khách hàng. Có lẽ tôi đang thiếu một cái gì đó?
Chiedo

@ jpmc26 Bạn thường xuyên làm cần thiết phải quan tâm nếu bạn sau một proxy từ xa. Nếu là bạn, thì IP hơn kết nối với bạn sẽ là máy chủ proxy từ xa và bạn sẽ cần phải dựa vào các tiêu đề mà nó thêm vào để có được IP máy khách gốc. Nếu bạn không phải , những tiêu đề đó thường sẽ không xuất hiện và bạn sẽ muốn sử dụng IP kết nối làm IP khách. Và bạn không nhất thiết chỉ cần kiểm tra tiêu đề và quay lại IP kết nối nếu nó không xuất hiện, vì sau đó nếu bạn không đứng sau proxy ngược, khách hàng có thể giả mạo IP của họ, trong nhiều trường hợp sẽ là vấn đề bảo mật .
Đánh dấu Amery

28

Địa chỉ IP của người dùng có thể được truy xuất bằng đoạn mã sau:

from flask import request
print(request.remote_addr)

3
Điều này không đúng nếu ứng dụng đang chạy phía sau máy chủ proxy như nginx . Mà nó thường là trong sản xuất.
datashaman

17

Tôi có Nginx và với bên dưới 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 giải pháp làm việc cho tôi

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

Yêu cầu và phản hồi của tôi:

curl -X GET http://test.api

{
    "ip": "Client Ip......"
}

13

Mã dưới đây luôn cung cấp IP công cộng của máy khách (và không phải là IP riêng đằng sau 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

Câu trả lời này cùng với việc thay đổi cấu hình nginx của tôi theo blog này đã làm việc cho tôi. calvin.me/forward-ip-addresses-when-USE-nginx-proxy
Romano Vacca

7

httpbin.org sử dụng phương pháp này:

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

Trả về 127.0.0.1do proxy, không hữu ích lắm.
Uri Goren

3

Nếu bạn sử dụng Nginx phía sau bộ cân bằng khác, ví dụ như Bộ cân bằng ứng dụng AWS, HTTP_X_FORWARDED_FOR trả về danh sách địa chỉ. Nó có thể được sửa như thế:

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

1

Nếu bạn đang sử dụng môi trường Gunicorn và Nginx thì mẫu mã sau đây phù hợp với bạn.

addr_ip4 = request.remote_addr

0

Điều này nên làm công việc. Nó cung cấp địa chỉ IP của máy khách (máy chủ từ xa).

Lưu ý rằng mã này đang chạy ở phía máy chủ.

from mod_python import apache

req.get_remote_host(apache.REMOTE_NOLOOKUP)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.