18

特定のユーザーに制限したいビューを持つ小さな Django アプリケーションがあります。特定のネットワークの誰でも、IP アドレスのみに基づいて、それ以上の認証なしでそのビューを見ることができるはずです。この IP 範囲外のユーザーは、パスワードを要求され、デフォルトの Django ユーザー管理に対して認証される必要があります。

そのためのカスタム認証バックエンドを作成する必要があると思いますが、authenticate()関数がユーザー名とパスワードの組み合わせまたはトークンを期待しているように見えるため、ドキュメントは私を混乱させます。ここで IP アドレスを使用して認証する方法が明確ではありません。

DjangoでIPアドレスベースの認証を実装する適切な方法は何ですか? セキュリティ関連のコードをすべて自分で作成するのではなく、できるだけ多くの既存のライブラリ関数を使用したいと考えています。

4

6 に答える 6

15

この種の認証には、次の 2 つの適切な方法があります。

  • デコレーターとして:一部のビュー (ただし、多くはありません) がこのチェックを必要とする場合は、そのためのデコレーターを作成することをお勧めします (@Jingo が作成したようなもの)。
  • ミドルウェアとして:デコレーターを使用する代わりに、すべての (または多くの) ビューでそのチェックを行う必要がある場合は、ミドルウェアを作成する方が良い解決策です。

サンプル ミドルウェアは次のようになります。

ALLOWED_IP_BLOCKS = [......]

class NeedToLoginMiddleware(object):
    def process_request(self, request):
        ip = request.META['REMOTE_ADDR']
        if not ip in ALLOWED_IP_BLOCKS: #ip check
            if not request.user.is_authenticated(): #if ip check failed, make authentication check
                return HttpResponseRedirect(...)
        return None
  • @Jingoが言及したように、リストまたは正規表現を使用してIPチェックを行うことができます。
  • django認証を使用していてリストにREMOTE_ADDRない場合は、関連するユーザーがログインしているかどうかを確認するために使用できます。ただし、カスタム ミドルウェアで使用する場合は、がそのレベルに設定されているため、カスタム ミドルウェアを の後に配置する必要があります。ALLOWED_IP_BLOCKSis_authenticatedis_authenticated AuthenticationMiddlewarerequest.user

    MIDDLEWARE_CLASSES = (
        ...
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'path.to.my.NeedToLoginMiddleware',
        ...
    )
    
    • この認証を必要としないビューがいくつかある場合は、例外的な URLのリストを作成し、そこからリクエスト URL を取得して、request.pathリクエスト URL に IP チェック/認証が必要かどうかを確認できます。

カスタム ミドルウェア クラスの詳細

于 2012-09-12T13:07:44.533 に答える
8

この目的のために小さなデコレータを作成することもできます。

def login_by_ip(view_func):
    def authorize(request, *args, **kwargs):
        user_ip = request.META['REMOTE_ADDR']
        for ip in allowedIps.allowedIps:
            authenticated_by_ip = re.compile(ip).match(user_ip)
            if authenticated_by_ip:
                return view_func(request, authenticated_by_ip, *args, **kwargs)
        return HttpResponseRedirect('/redirect/path/')
    return authorize

私の場合、allowedIpsは、許可されたIPの正規表現を次のようなタプルに格納するファイル(allowedIps.py)です。

allowedIps = ('^XXX\.XXX\..+\..+$','^XXX\.XXX\.XXX\..+$', '^XXX\.XXX\.XXX\.XXX$')

これがお役に立てば幸いです。注:authenticated_by_ipを装飾されたビューに戻す場合、ビューはそのパラメーターを受け入れる必要があります。必要がない場合は、省略してもかまいません。3桁までの数字のみを受け入れるように、正規表現をより正確に定義することもできます。

于 2012-09-12T08:56:52.880 に答える
4

IMO、パフォーマンスが重要でない小さなサイトであれば、Django でこれを解決しても問題ありません。

Apache または Nginx サービスを使用して、許可されていないユーザーを完全に寄せ付けないようにすることをお勧めします。たとえば、Nginx では、サイト構成に次の行があります。

include allowed_ips.conf;
deny all;
error_page 403 forbidden.html;

allowed_ips.conf は /etc/nginx にあり、(何か) 次のようになります。

allow 110.222.333.222;  # J Bloggs (sys admin)
allow 777.222.0.0/16;   # Government owned
...

比較的遅い Django プロセスがブロックされた IP に影響されないため、これはより良いことだと思います。これは、パフォーマンスまたはセキュリティ上の理由でボットまたは他の国のアドレス範囲をブロックしている場合に重要です。

于 2013-12-30T00:08:18.730 に答える
4

このデコレータを試すことができます。私は正常に動作することをテストしました:

allowedIps = ['129.0.0.1', '127.0.0.1']
def allow_by_ip(view_func):
    def authorize(request, *args, **kwargs):
        user_ip = request.META['REMOTE_ADDR']
        for ip in allowedIps:
            if ip==user_ip:
                return view_func(request, *args, **kwargs)
        return HttpResponse('Invalid Ip Access!')
    return authorize
于 2015-08-10T14:59:16.467 に答える
3

作成したユース ケースの認証バックエンドを作成する必要はありません。ミドルウェア層に IP ベースのディスパッチャを書くだけで十分でしょう

アプリの URL が一致する場合、process_request は認証済みの django ユーザーをチェックし、そのユーザーをホワイトリストと照合する必要があります。

于 2012-09-12T07:58:12.350 に答える
1
def login_by_id(request):
    ip = request.META['REMOTE_ADDR']
    try: UserProfile.objects.get(allow_ip=ip)
    except UserProfile.DoesNotExist: return HttpResponseRedirect('././')
    else:
        # auth here

allow_ipユーザーの編集ページでの登録または変更を保存する UserProfile モデルが必要です

于 2012-09-12T11:40:36.277 に答える