How do I get user IP address in django?

后端 未结 11 1129
野趣味
野趣味 2020-11-22 15:33

How do I get user\'s IP in django?

I have a view like this:

# Create your views
from django.contrib.gis.utils import GeoIP
from django.template impor         


        
相关标签:
11条回答
  • 2020-11-22 16:09

    The simpliest solution (in case you are using fastcgi+nignx) is what itgorilla commented:

    Thank you for this great question. My fastcgi was not passing the REMOTE_ADDR meta key. I added the line below in the nginx.conf and fixed the problem: fastcgi_param REMOTE_ADDR $remote_addr; – itgorilla

    Ps: I added this answer just to make his solution more visible.

    0 讨论(0)
  • 2020-11-22 16:10

    I would like to suggest an improvement to yanchenko's answer.

    Instead of taking the first ip in the X_FORWARDED_FOR list, I take the first one which in not a known internal ip, as some routers don't respect the protocol, and you can see internal ips as the first value of the list.

    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
    

    I hope this helps fellow Googlers who have the same problem.

    0 讨论(0)
  • 2020-11-22 16:15

    I was also missing proxy in above answer. I used get_ip_address_from_request from 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
    

    And here is method get_ip_address_from_request, IPv4 and IPv6 ready:

    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
    
    0 讨论(0)
  • 2020-11-22 16:16
    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
    

    Make sure you have reverse proxy (if any) configured correctly (e.g. mod_rpaf installed for Apache).

    Note: the above uses the first item in X-Forwarded-For, but you might want to use the last item (e.g., in the case of Heroku: Get client's real IP address on Heroku)

    And then just pass the request as argument to it;

    get_client_ip(request)
    
    0 讨论(0)
  • 2020-11-22 16:19

    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")
    

    for more info check the Django Docs

    0 讨论(0)
  • 2020-11-22 16:21

    In django.VERSION (2, 1, 1, 'final', 0) request handler

    sock=request._stream.stream.raw._sock
    #<socket.socket fd=1236, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.1.111', 8000), raddr=('192.168.1.111', 64725)>
    client_ip,port=sock.getpeername()
    

    if you call above code twice,you may got

    AttributeError("'_io.BytesIO' object has no attribute 'stream'",)

    AttributeError("'LimitedStream' object has no attribute 'raw'")

    0 讨论(0)
提交回复
热议问题