21
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

DjangoでクライアントのIPアドレスを取得する

Last updated at Posted at 2019-11-03

直接アクセスのみ

クライアントが Django に直接アクセスすると決まっている場合は、HTTP ヘッダの'REMOTE_ADDR'を参照するだけで IP アドレスを取得することができます。

views.py
from django.http import HttpResponse
from django.views import View

class MyView(View):
    def get(self, request):
        # request オブジェクトから'REMOTE_ADDR'ヘッダを取得する。
        client_addr = request.META.get('REMOTE_ADDR')

        # 動作確認のため、取得したアドレスをそのまま返す。
        return HttpResponse(client_addr)

リバースプロキシ対応

しかし上記の方法では、クライアントと Django の間に Nginx などのリバースプロキシがある場合は、'REMOTE_ADDR'で取得できる IP アドレスがリバースプロキシのアドレスになってしまいます(例: Nginx が同じホストにあると127.0.0.1になる)。

途中で1回以上転送された場合は、同じく HTTP ヘッダの'HTTP_X_FORWARDED_FOR'を参照すれば転送経路の IP アドレスがカンマ区切り文字列で取得できるので、この先頭要素からクライアントの IP アドレスを取得することができます。

また'HTTP_X_FORWARDED_FOR'ヘッダがない場合は直接アクセスなので、上記と同様に'REMOTE_ADDR'で取得します。

views.py
from django.http import HttpResponse
from django.views import View

class MyView(View):
    def get(self, request):
        # 'HTTP_X_FORWARDED_FOR'ヘッダを参照して転送経路のIPアドレスを取得する。
        forwarded_addresses = request.META.get('HTTP_X_FORWARDED_FOR')
        if forwarded_addresses:
            # 'HTTP_X_FORWARDED_FOR'ヘッダがある場合: 転送経路の先頭要素を取得する。
            client_addr = forwarded_addresses.split(',')[0]
        else:
            # 'HTTP_X_FORWARDED_FOR'ヘッダがない場合: 直接接続なので'REMOTE_ADDR'ヘッダを参照する。
            client_addr = request.META.get('REMOTE_ADDR')

        # 動作確認のため、取得したアドレスをそのまま返す。
        return HttpResponse(client_addr)

ipwareを使う

django-ipware を pip でインストールします。

pip3 install django-ipware

インポートしてget_client_ip関数を使えば、たった 1行でクライアントのアドレスを取得でき、もちろんリバースプロキシに対応しています。

views.py
from django.http import HttpResponse
from django.views import View
from ipware import get_client_ip

class MyView(View):
    def get(self, request):
        client_addr, _ = get_client_ip(request)

        return HttpResponse(client_addr)

参照する HTTP ヘッダは'HTTP_X_FORWARDED_FOR''REMOTE_ADDR'だけでなく、デフォルトで以下の優先順位でクライアントのアドレスを取得します。

 # The default meta precedence order
 IPWARE_META_PRECEDENCE_ORDER = (
     'HTTP_X_FORWARDED_FOR', 'X_FORWARDED_FOR',  # <client>, <proxy1>, <proxy2>
     'HTTP_CLIENT_IP',
     'HTTP_X_REAL_IP',
     'HTTP_X_FORWARDED',
     'HTTP_X_CLUSTER_CLIENT_IP',
     'HTTP_FORWARDED_FOR',
     'HTTP_FORWARDED',
     'HTTP_VIA',
     'REMOTE_ADDR',
 )

さらにget_client_ip関数を呼び出す時に、指定した優先順位でデフォルトの優先順位をオーバーライドすることもできます。

client_addr, is_routable = get_client_ip(request, request_header_order=['X_FORWARDED_FOR', 'REMOTE_ADDR'])

参考リンク

Stack Overflow "How do I get user IP address in django?"
https://stackoverflow.com/questions/4581789/how-do-i-get-user-ip-address-in-django

GitHub - un33k/django-ipware "A Django application to retrieve client's IP address"
https://github.com/un33k/django-ipware

21
15
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?