391 Stimmen

Wie erhalte ich die IP-Adresse des Benutzers in Django?

Wie erhalte ich die IP des Benutzers in Django?

Ich habe eine solche Ansicht:

# Create your views
from django.contrib.gis.utils import GeoIP
from django.template import  RequestContext
from django.shortcuts import render_to_response

def home(request):
  g = GeoIP()
  client_ip = request.META['REMOTE_ADDR']
  lat,long = g.lat_lon(client_ip)
  return render_to_response('home_page_tmp.html',locals())

Aber ich erhalte diesen Fehler:

KeyError at /mypage/
    'REMOTE_ADDR'
    Request Method: GET
    Request URL:    http://mywebsite.example/mypage/
    Django Version: 1.2.4
    Exception Type: KeyError
    Exception Value:
    'REMOTE_ADDR'
    Exception Location: /mysite/homepage/views.py in home, line 9
    Python Executable:  /usr/bin/python
    Python Version: 2.6.6
    Python Path:    ['/mysite', '/usr/local/lib/python2.6/dist-packages/flup-1.0.2-py2.6.egg', '/usr/lib/python2.6', '/usr/lib/python2.6/plat-linux2', '/usr/lib/python2.6/lib-tk', '/usr/lib/python2.6/lib-old', '/usr/lib/python2.6/lib-dynload', '/usr/local/lib/python2.6/dist-packages', '/usr/lib/python2.6/dist-packages', '/usr/lib/pymodules/python2.6']
    Server time:    Sun, 2 Jan 2011 20:42:50 -0600

2 Stimmen

Versuchen Sie, request.META.keys() zu dumpen.

3 Stimmen

['HTTP_COOKIE', 'SCRIPT_NAME', 'REQUEST_METHOD', 'PATH_INFO', 'SERVER_PROTOCOL', 'QUERY_STRING', 'CONTENT_LENGTH', 'HTTP_ACCEPT_CHARSET', 'HTTP_USER_AGENT', 'HTTP_CONNECTION', 'SERVER_NAME', 'wsgi.url_scheme', 'SERVER_PORT', 'wsgi. input', 'HTTP_HOST', 'wsgi.multithread', 'HTTP_CACHE_CONTROL', 'HTTP_ACCEPT', 'wsgi.version', 'wsgi.run_once', 'wsgi.errors', 'wsgi.multiprocess', 'HTTP_ACCEPT_LANGUAGE', 'CONTENT_TYPE', 'CSRF_COOKIE', 'HTTP_ACCEPT_ENCODING']

3 Stimmen

Ich danke Ihnen für diese großartige Frage. Mein fastcgi hat den Metaschlüssel REMOTE_ADDR nicht übergeben. Ich habe die folgende Zeile in der nginx.conf hinzugefügt und das Problem behoben: fastcgi_param REMOTE_ADDR $remote_addr;

13voto

evilscientress Punkte 151

Hier ist ein kurzer Einzeiler, um dies zu erreichen:

request.META.get('HTTP_X_FORWARDED_FOR', request.META.get('REMOTE_ADDR', '')).split(',')[0].strip()

10 Stimmen

Wenn beide keinen Wert zurückgeben, erhalten Sie einen Fehler.

0 Stimmen

Es funktioniert wirklich, es liefert Ihre aktuelle öffentliche IP-Adresse, danke @masterbase, Sie haben mir den Tag versüßt.

0 Stimmen

@GouravChawla einige ziemlich einfache bedingte Logik würde verhindern, dass dies zu Fehlern führt remote_ip = request.META.get('HTTP_X_FORWARDED_FOR', request.META.get('REMOTE_ADDR', '')) if remote_ip = remote_ip.split(',')[0] if remote_ip else None

8voto

xxmajia Punkte 558

In meinem Fall funktioniert keine der oben genannten Möglichkeiten, also muss ich prüfen uwsgi + django Quellcode und übergeben statische param in nginx und sehen, warum / wie, und unten ist, was ich gefunden habe.

Env-Informationen:
Python-Version: 2.7.5
Django-Version: (1, 6, 6, 'final', 0)
nginx-Version: nginx/1.6.0
uwsgi: 2.0.7

Informationen zur Einstellung der Umgebungsbedingungen:
nginx als Reverse-Proxy, der an Port 80 uwsgi als vorgelagerter Unix-Socket, wird die Anfrage schließlich beantworten

Django-Konfigurationsdaten:

USE_X_FORWARDED_HOST = True # with or without this line does not matter

nginx-Konfiguration:

uwsgi_param      X-Real-IP              $remote_addr;
// uwsgi_param   X-Forwarded-For        $proxy_add_x_forwarded_for;
// uwsgi_param   HTTP_X_FORWARDED_FOR   $proxy_add_x_forwarded_for;

// hardcode for testing
uwsgi_param      X-Forwarded-For        "10.10.10.10";
uwsgi_param      HTTP_X_FORWARDED_FOR   "20.20.20.20";

alle Parameter in der Django-App zu erhalten:

X-Forwarded-For :       10.10.10.10
HTTP_X_FORWARDED_FOR :  20.20.20.20

Schlussfolgerung:

Im Grunde müssen Sie also genau denselben Feld-/Param-Namen in nginx angeben und mit request.META[field/param] in der Django-App.

Und jetzt können Sie entscheiden, ob Sie eine Middleware (Interceptor) hinzufügen oder einfach nur parsen HTTP_X_FORWARDED_FOR in bestimmten Ansichten.

7voto

Juande Carrion Punkte 730

Die einfachste Lösung (für den Fall, dass Sie fastcgi+nignx verwenden) ist das, was itgorilla kommentiert hat:

Ich danke Ihnen für diese großartige Frage. Mein fastcgi hat den Metaschlüssel REMOTE_ADDR nicht übergeben. Ich habe die folgende Zeile in der nginx.conf hinzugefügt und das Problem behoben: fastcgi_param REMOTE_ADDR $remote_addr; - Itgorilla

Ps: Ich habe diese Antwort nur hinzugefügt, um seine Lösung besser sichtbar zu machen.

3 Stimmen

Was ist eine vergleichbare Lösung für nginx (Reverse Proxy) und gunicorn? proxy_set_header REMOTE_ADDR $remote_addr; lindert das Problem nicht, wenn es zur nginx.conf hinzugefügt wird.

4voto

ferrix Punkte 761

Der Grund, warum diese Funktion ursprünglich aus Django entfernt wurde, war, dass man dem Header letztlich nicht trauen kann. Der Grund ist, dass er leicht zu fälschen ist. Der empfohlene Weg, einen Nginx-Reverse-Proxy zu konfigurieren, ist zum Beispiel folgender:

add_header X-Forwarded-For $proxy_add_x_forwarded_for;
add_header X-Real-Ip       $remote_addr;

Wenn Sie das tun:

curl -H 'X-Forwarded-For: 8.8.8.8, 192.168.1.2' http://192.168.1.3/

Ihr Nginx in myhost.example weiterschicken wird:

X-Forwarded-For: 8.8.8.8, 192.168.1.2, 192.168.1.3

En X-Real-IP ist die IP des ersten vorherigen Proxys, wenn Sie die Anweisungen blind befolgen.

Falls es ein Problem ist, den Nutzern zu vertrauen, könnten Sie etwas wie folgt versuchen django-xff : https://pypi.python.org/pypi/django-xff/

3voto

Lucas03 Punkte 2182

In der obigen Antwort fehlte auch ein Proxy. Ich habe get_ip_address_from_request de django_easy_timezones .

from easy_timezones.utils import get_ip_address_from_request, is_valid_ip, is_local_ip
ip = get_ip_address_from_request(request)
try:
    if is_valid_ip(ip):
        geoip_record = IpRange.objects.by_ip(ip)
except IpRange.DoesNotExist:
    return None

Und hier die Methode get_ip_address_from_request , IPv4 und IPv6 bereit:

def get_ip_address_from_request(request):
    """ Makes the best attempt to get the client's real IP or return the loopback """
    PRIVATE_IPS_PREFIX = ('10.', '172.', '192.', '127.')
    ip_address = ''
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR', '')
    if x_forwarded_for and ',' not in x_forwarded_for:
        if not x_forwarded_for.startswith(PRIVATE_IPS_PREFIX) and is_valid_ip(x_forwarded_for):
            ip_address = x_forwarded_for.strip()
    else:
        ips = [ip.strip() for ip in x_forwarded_for.split(',')]
        for ip in ips:
            if ip.startswith(PRIVATE_IPS_PREFIX):
                continue
            elif not is_valid_ip(ip):
                continue
            else:
                ip_address = ip
                break
    if not ip_address:
        x_real_ip = request.META.get('HTTP_X_REAL_IP', '')
        if x_real_ip:
            if not x_real_ip.startswith(PRIVATE_IPS_PREFIX) and is_valid_ip(x_real_ip):
                ip_address = x_real_ip.strip()
    if not ip_address:
        remote_addr = request.META.get('REMOTE_ADDR', '')
        if remote_addr:
            if not remote_addr.startswith(PRIVATE_IPS_PREFIX) and is_valid_ip(remote_addr):
                ip_address = remote_addr.strip()
    if not ip_address:
        ip_address = '127.0.0.1'
    return ip_address

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X