How do I get user IP address in django?

后端 未结 11 1138
野趣味
野趣味 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:23

    The reason the functionality was removed from Django originally was that the header cannot ultimately be trusted. The reason is that it is easy to spoof. For example the recommended way to configure an nginx reverse proxy is to:

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

    When you do:

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

    Your nginx in myhost.com will send onwards:

    X-Forwarded-For: 8.8.8.8, 192.168.1.2, 192.168.1.3
    

    The X-Real-IP will be the IP of the first previous proxy if you follow the instructions blindly.

    In case trusting who your users are is an issue, you could try something like django-xff: https://pypi.python.org/pypi/django-xff/

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

    You can use django-ipware which supports Python 2 & 3 and handles IPv4 & IPv6.

    Install:

    pip install django-ipware

    Simple Usage:

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

    Advanced Usage:

    • Custom Header - Custom request header for ipware to look at:

      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 is behind a fixed number of proxies:

      i, r = get_client_ip(request, proxy_count=1)
      
    • Trusted Proxies - Django server is behind one or more known & trusted 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.'))
      

    Note: read this notice.

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

    here is a short one liner to accomplish this:

    request.META.get('HTTP_X_FORWARDED_FOR', request.META.get('REMOTE_ADDR', '')).split(',')[0].strip()
    
    0 讨论(0)
  • 2020-11-22 16:35

    Alexander's answer is great, but lacks the handling of proxies that sometimes return multiple IP's in the HTTP_X_FORWARDED_FOR header.

    The real IP is usually at the end of the list, as explained here: http://en.wikipedia.org/wiki/X-Forwarded-For

    The solution is a simple modification of Alexander's 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
    
    0 讨论(0)
  • 2020-11-22 16:35

    In my case none of above works, so I have to check uwsgi + django source code and pass static param in nginx and see why/how, and below is what I have found.

    Env info:
    python version: 2.7.5
    Django version: (1, 6, 6, 'final', 0)
    nginx version: nginx/1.6.0
    uwsgi: 2.0.7

    Env setting info:
    nginx as reverse proxy listening at port 80 uwsgi as upstream unix socket, will response to the request eventually

    Django config info:

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

    nginx config:

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

    getting all the params in django app:

    X-Forwarded-For :       10.10.10.10
    HTTP_X_FORWARDED_FOR :  20.20.20.20
    

    Conclusion:

    So basically, you have to specify exactly the same field/param name in nginx, and use request.META[field/param] in django app.

    And now you can decide whether to add a middleware (interceptor) or just parse HTTP_X_FORWARDED_FOR in certain views.

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