Como obtenho o IP do usuário no django?
Eu tenho uma visão como esta:
# 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())
Mas eu recebo este erro:
KeyError at /mypage/
'REMOTE_ADDR'
Request Method: GET
Request URL: http://mywebsite.com/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
Respostas:
Verifique se o proxy reverso (se houver) está configurado corretamente (por exemplo,
mod_rpaf
instalado para o Apache).Nota: o item acima usa o primeiro item
X-Forwarded-For
, mas você pode usar o último item (por exemplo, no caso do Heroku: obter o endereço IP real do cliente no Heroku )E então apenas passe a solicitação como argumento para ela;
fonte
ip = get_client_ip(request)
sua função de visualização.X-Forwarded-For: client, proxy1, proxy2
. Portanto, o primeiro endereço é do cliente.Você pode usar o django-ipware que suporta Python 2 e 3 e lida com IPv4 e IPv6 .
Instalar:
pip install django-ipware
Uso simples:
Uso avançado:
Cabeçalho personalizado - Cabeçalho de solicitação personalizado para o ipware olhar para:
Contagem de Proxy - O servidor Django está atrás de um número fixo de proxies:
Proxies Confiáveis - O servidor Django está atrás de um ou mais proxies conhecidos e confiáveis:
Nota: leia este aviso .
fonte
IPWARE_META_PRECEDENCE_LIST
para a variável que você usa, ou usar uma alternativa como pypi.python.org/pypi/WsgiUnproxyget_client_ip()
.get_real_ip
foi descontinuado e será removido no 3.0.A resposta de Alexander é ótima, mas falta o tratamento de proxies que às vezes retornam vários IPs no cabeçalho HTTP_X_FORWARDED_FOR.
O IP real geralmente está no final da lista, conforme explicado aqui: http://en.wikipedia.org/wiki/X-Forwarded-For
A solução é uma simples modificação do código de Alexander:
fonte
request.META
, incluo um valor padrão, pois os cabeçalhos costumam aparecer:request.META.get('REMOTE_ADDR', None)
Eu gostaria de sugerir uma melhoria na resposta de yanchenko.
Em vez de pegar o primeiro ip na lista X_FORWARDED_FOR, eu pego o primeiro que não é um ip interno conhecido, pois alguns roteadores não respeitam o protocolo e você pode ver os ips internos como o primeiro valor da lista.
Espero que isso ajude outros Googlers que têm o mesmo problema.
fonte
aqui está uma lista curta para fazer isso:
fonte
A solução mais simples (caso você esteja usando o fastcgi + nignx) é o que o itgorilla comentou:
Ps: eu adicionei esta resposta apenas para tornar sua solução mais visível.
fonte
proxy_set_header REMOTE_ADDR $remote_addr;
não alivia o problema quando adicionado ao nginx.conf.Sem mais confusão Nas versões recentes do Django, é mencionado claramente que o endereço IP do cliente está disponível em
para mais informações consulte o Django Docs
fonte
No meu caso, nenhuma das opções acima funciona, então eu tenho que verificar o
uwsgi
+django
código-fonte e passar o parâmetro estático no nginx e ver por que / como e abaixo está o que encontrei.Informações do Env:
python version:
2.7.5
Django version:
(1, 6, 6, 'final', 0)
nginx version:
nginx/1.6.0
uwsgi:
2.0.7
Informações da configuração do Env:
nginx como proxy reverso escutando na porta
80
uwsgi como soquete unix upstream, responderá à solicitação eventualmenteInformações de configuração do Django:
configuração nginx:
obtendo todos os parâmetros no aplicativo django:
Conclusão:
Então, basicamente, você deve especificar exatamente o mesmo nome de campo / parâmetro no nginx e usar
request.META[field/param]
no aplicativo django.E agora você pode decidir se deseja adicionar um middleware (interceptador) ou apenas analisar
HTTP_X_FORWARDED_FOR
em determinadas visualizações.fonte
A razão pela qual a funcionalidade foi removida do Django originalmente foi que o cabeçalho não pode ser confiável. A razão é que é fácil falsificar. Por exemplo, a maneira recomendada de configurar um proxy reverso nginx é:
Quando você faz:
Seu nginx em myhost.com enviará adiante:
A
X-Real-IP
será o IP do primeiro proxy anterior se você seguir as instruções cegamente.No caso de confiar em quem são seus usuários, você pode tentar algo como
django-xff
: https://pypi.python.org/pypi/django-xff/fonte
Também estava faltando proxy na resposta acima. Eu usei
get_ip_address_from_request
de django_easy_timezones .E aqui está o método
get_ip_address_from_request
, pronto para IPv4 e IPv6:fonte
No manipulador de solicitações django.VERSION (2, 1, 1, 'final', 0)
se você chamar o código acima duas vezes, poderá receber
AttributeError ("o objeto '_ io.BytesIO' não possui atributo 'stream'",)
AttributeError ("O objeto 'LimitedStream' não tem atributo 'bruto'")
fonte