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;

585voto

yanchenko Punkte 55207
def get_client_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip

Vergewissern Sie sich, dass Sie den Reverse-Proxy (falls vorhanden) richtig konfiguriert haben (z. B. mod_rpaf für Apache installiert).

Hinweis: Die obige Darstellung verwendet die erste Artikel in X-Forwarded-For verwenden, aber Sie könnten die zuletzt Element (z. B. im Fall von Heroku: Abrufen der echten IP-Adresse des Kunden auf Heroku )

Und dann übergeben Sie einfach die Anfrage als Argument an sie;

get_client_ip(request)

Django-Dokumentation für HttpRequest.META

1 Stimmen

Ich verwende django + nginx + fastcgi

1 Stimmen

Trotzdem sollten Sie den Inhalt von request.META protokollieren und Ihre Serverkonfiguration anpassen, wenn weder 'HTTP_X_FORWARDED_FOR' noch 'REMOTE_ADDR' Schlüssel ist da.

0 Stimmen

Wie verwende ich die Funktion "get_client_ip" in meiner Ansicht? --Danke!

266voto

un33k Punkte 16338

Sie können verwenden django-ipware die Python unterstützt 2 & 3 und Griffe IPv4 & IPv6 .

Installieren:

pip install django-ipware

Einfache Verwendung:

# In a view or a middleware where the `request` object is available

from ipware import get_client_ip
ip, is_routable = get_client_ip(request)
if ip is None:
    # Unable to get the client's IP address
else:
    # We got the client's IP address
    if is_routable:
        # The client's IP address is publicly routable on the Internet
    else:
        # The client's IP address is private

# Order of precedence is (Public, Private, Loopback, None)

Erweiterte Verwendung:

  • Benutzerdefinierte Kopfzeile - Benutzerdefinierte Kopfzeile der Anfrage, die von ipware betrachtet wird:

    i, r = get_client_ip(request, request_header_order=['X_FORWARDED_FOR'])
    i, r = get_client_ip(request, request_header_order=['X_FORWARDED_FOR', 'REMOTE_ADDR'])
  • Proxy Count - Django Server ist hinter einer festen Anzahl von Proxies:

    i, r = get_client_ip(request, proxy_count=1)
  • Vertrauenswürdige Proxies - Der Django-Server befindet sich hinter einem oder mehreren bekannten und vertrauenswürdigen Proxies:

    i, r = get_client_ip(request, proxy_trusted_ips=('177.2.2.2'))
    
    # For multiple proxies, simply add them to the list
    i, r = get_client_ip(request, proxy_trusted_ips=('177.2.2.2', '177.3.3.3'))
    
    # For proxies with fixed sub-domain and dynamic IP addresses, use partial pattern
    i, r = get_client_ip(request, proxy_trusted_ips=('177.2.', '177.3.'))

Anmerkung: dies lesen Hinweis .

23 Stimmen

Schauen Sie sich den Quellcode an. Er behandelt alle Komplikationen, die in den anderen Antworten genannt wurden.

5 Stimmen

Thx @Heliodor -- Yep, ich habe das Modul sehr einfach für einen durchschnittlichen Anwendungsfall und sehr flexibel für einen komplexen Anwendungsfall gemacht. Minimal, würden Sie wollen, um seine Github-Seite zu sehen, bevor Sie Ihre eigenen rollen.

3 Stimmen

Beachten Sie, dass die Einstellungen von django-ipware standardmäßig nicht sicher sind! Jeder kann eine der anderen Variablen übergeben und Ihre Website wird diese IP protokollieren. Immer setzen IPWARE_META_PRECEDENCE_LIST auf die Variable, die Sie verwenden, oder verwenden Sie eine Alternative wie pypi.python.org/pypi/WsgiUnproxy

95voto

Sævar Punkte 1557

Alexanders Antwort ist großartig, aber es fehlt die Behandlung von Proxies, die manchmal mehrere IPs im HTTP_X_FORWARDED_FOR-Header zurückgeben.

Die eigentliche IP befindet sich in der Regel am Ende der Liste, wie hier erläutert: http://en.wikipedia.org/wiki/X-Forwarded-For

Die Lösung ist eine einfache Änderung von Alexanders Code:

def get_client_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[-1].strip()
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip

1 Stimmen

Ist es die IP bei der Ende der Liste? Wenn ich den Wikipedia-Link lese, heißt es, dass "der am weitesten links stehende Client der am weitesten nachgelagerte Client ist", was so klingt, als sei der erste Wert der ursprüngliche Client. Oder macht Django es umgekehrt?

11 Stimmen

Ja, die IP ist auf der Anfang der Liste. Das hier ist falsch.

4 Stimmen

Wenn sich der Benutzer hinter einem Proxy befindet, würden Sie die interne IP-Adresse des Benutzers erhalten, d. h. eine RFC 1918-Adresse. In den meisten Fällen ist das nicht sehr wünschenswert. Diese Lösung konzentriert sich darauf, die externe IP-Adresse des Clients (die Proxy-Adresse) zu erhalten, die die Adresse ganz rechts ist.

31voto

Pardhu Punkte 1491

Keine Verwirrung mehr In den neueren Versionen von Django wird deutlich erwähnt, dass die IP-Adresse des Clients verfügbar ist unter

request.META.get("REMOTE_ADDR")

Weitere Informationen finden Sie auf der Django-Dokumente

9 Stimmen

Dieser Wert ist leer, wenn die Anwendung hinter einem Reverse-Proxy-Server (wie Nginx) ausgeführt wird. Sie benötigen X_FORWARDED_FOR

19voto

Doody P Punkte 3351

Ich möchte eine Verbesserung der Antwort von yanchenko vorschlagen.

Anstatt die erste IP in der X_FORWARDED_FOR-Liste zu nehmen, nehme ich die erste, die keine bekannte interne IP ist, da einige Router das Protokoll nicht respektieren, und Sie können interne IPs als ersten Wert der Liste sehen.

PRIVATE_IPS_PREFIX = ('10.', '172.', '192.', )

def get_client_ip(request):
    """get the client ip from the request
    """
    remote_address = request.META.get('REMOTE_ADDR')
    # set the default value of the ip to be the REMOTE_ADDR if available
    # else None
    ip = remote_address
    # try to get the first non-proxy ip (not a private ip) from the
    # HTTP_X_FORWARDED_FOR
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        proxies = x_forwarded_for.split(',')
        # remove the private ips from the beginning
        while (len(proxies) > 0 and
                proxies[0].startswith(PRIVATE_IPS_PREFIX)):
            proxies.pop(0)
        # take the first ip which is not a private one (of a proxy)
        if len(proxies) > 0:
            ip = proxies[0]

    return ip

Ich hoffe, dies hilft anderen Googlern, die das gleiche Problem haben.

0 Stimmen

Dieser Code prüft nicht, ob die IP-Adresse aus REMOTE_ADDR privat ist, bevor er das HTTP_X_FORWARDED_FOR-Feld prüft, was er wahrscheinlich tun sollte (außerdem sollten '127.0.0.1' oder '127.' zusammen mit IPv6-Äquivalenten wahrscheinlich in PRIVATE_IPS_PREFIX enthalten sein.

3 Stimmen

Technisch gesehen bedeuten diese Präfixe (172, 192) nicht unbedingt private Adressen.

2 Stimmen

Die für private Netze zugewiesenen Adressbereiche sind: 172.16.0.0-172.31.255.255 (16 "Klasse B"-Netze), 192.168.0.0-192.168.255.255 (1 "Klasse B"-Netz) und 10.0.0.0-10.255.255.255 (1 "Klasse A"- oder 256 "Klasse B"-Netze).

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