如何在django中获取用户的IP?
我有这样的观点:
# 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())
Run Code Online (Sandbox Code Playgroud)
但我得到这个错误:
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
Run Code Online (Sandbox Code Playgroud)
yan*_*nko 393
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
Run Code Online (Sandbox Code Playgroud)
确保正确配置了反向代理(如果有)(例如,mod_rpaf为Apache安装).
注意:以上使用了第一项X-Forwarded-For,但您可能想要使用最后一项(例如,在Heroku的情况下:在Heroku上获取客户端的真实IP地址)
然后将请求作为参数传递给它;
get_client_ip(request)
Run Code Online (Sandbox Code Playgroud)
un3*_*33k 198
您可以使用支持Python 2和3的django-ipware并处理IPv4和IPv6.
安装:
pip install django-ipware
简单用法:
获取客户端的IP地址.
# 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)
Run Code Online (Sandbox Code Playgroud)
高级用法:
自定义标题 - 用于查看ipware的自定义请求标头
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'])
Run Code Online (Sandbox Code Playgroud)
代理计数 - Django服务器支持固定数量的代理
i, r = get_client_ip(request, proxy_count=1)
Run Code Online (Sandbox Code Playgroud)
受信任的代理 - Django服务器支持一个或多个已知和受信任的代理
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.'))
Run Code Online (Sandbox Code Playgroud)
注意:阅读此通知.
Sæv*_*var 76
亚历山大的答案很棒,但缺乏有时在HTTP_X_FORWARDED_FOR标头中返回多个IP的代理的处理.
真正的IP通常位于列表的末尾,如下所述:http://en.wikipedia.org/wiki/X-Forwarded-For
解决方案是对Alexander代码的简单修改:
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
Run Code Online (Sandbox Code Playgroud)
Par*_*dhu 24
No More confusion In the recent versions of Django it is mentioned clearly that the Ip address of the client is available at
request.META.get("REMOTE_ADDR")
Run Code Online (Sandbox Code Playgroud)
for more info check the Django Docs
我想建议改进yanchenko的答案.
我没有在X_FORWARDED_FOR列表中取第一个ip,而是采用第一个不是已知内部ip的ip,因为有些路由器不遵守协议,你可以看到内部ips作为列表的第一个值.
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
Run Code Online (Sandbox Code Playgroud)
我希望这可以帮助那些遇到同样问题的Google员工.
这是完成此任务的简短说明:
request.META.get('HTTP_X_FORWARDED_FOR', request.META.get('REMOTE_ADDR', '')).split(',')[0].strip()
Run Code Online (Sandbox Code Playgroud)
最简单的解决方案(如果你使用fastcgi + nignx)是itgorilla评论的:
谢谢你提出这个好问题.我的fastcgi没有传递REMOTE_ADDR元键.我在nginx.conf中添加了以下行并修复了问题:fastcgi_param REMOTE_ADDR $ remote_addr; - 伊戈里拉
Ps:我添加了这个答案只是为了让他的解决方案更加明显.
就我而言,上述方法均无效,因此我必须检查uwsgi+ django源代码并在nginx中传递静态参数,并查看原因/方式,以下是我发现的内容。
信封信息:
python版本:2.7.5
Django版本:(1, 6, 6, 'final', 0)
nginx版本:nginx/1.6.0
uwsgi:2.0.7
环境设置信息:
nginx作为反向代理,在端口80
uwsgi处作为上游unix套接字侦听,最终将响应请求
Django配置信息:
USE_X_FORWARDED_HOST = True # with or without this line does not matter
Run Code Online (Sandbox Code Playgroud)
Nginx的配置:
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";
Run Code Online (Sandbox Code Playgroud)
在Django应用中获取所有参数:
X-Forwarded-For : 10.10.10.10
HTTP_X_FORWARDED_FOR : 20.20.20.20
Run Code Online (Sandbox Code Playgroud)
结论:
因此,基本上,您必须在nginx中指定完全相同的字段/参数名称,并request.META[field/param]在django应用中使用。
现在,您可以决定是添加中间件(拦截器)还是仅HTTP_X_FORWARDED_FOR在某些视图中进行解析。
| 归档时间: |
|
| 查看次数: |
156659 次 |
| 最近记录: |