この記事では、ミドルウェアを使用せずにDjangoの各ViewでURLを使用した直接アクセスを禁止する方法方法を説明します。
システム (アプリ) 全体では設定したくない時に各ページ個別に設定するのに使用します。
この記事の内容です。
対象読者
- 各ページ個別に直接アクセスをしたい方
環境
- Django (version 4.1.2, 3.2.16)
前提条件
- Viewの実装はViewクラスを継承したクラスで実装している
各Viewで直接アクセスを禁止する方法
単純な直接アクセス禁止
以下のように、何かしらのViewクラスを継承したクラスにて、
get関数をオーバーライドしホストやアクセス元URLを元に直接アクセスか否かをチェックします。
以下の例では、hogeアプリの/reservationからしかアクセスできない/confirm-reservationへ直接アクセスされた際に、トップページを強制的に開かせるようにしています。
また、URLについてはurls.pyにそれぞれ登録されていること前提です。
from django.views.generic import TemplateView
from urllib import parse
class ConfirmReservationView(TemplateView):
# 省略
def get(self, request, *args, **kwargs):
referer = self.request.environ.get('HTTP_REFERER')
parsed_referer_url = parse.urlparse(referer)
if not (self.request.get_host() == parsed_referer_url.netloc
and parsed_referer_url.path == reverse('hoge:reservation')):
return HttpResponseRedirect(reverse('hoge:top'))
return super().get(request, *args, **kwargs)
# 省略
フォームの値ありきのパターンの直接アクセス禁止
単純な直接アクセス禁止 で説明したコードに対し、それぞれセッションやPOSTメソッドで渡された値をチェックすることで他のパターンで直接アクセスを検知することができます。
ここらへんは、それぞれ要求や仕様に応じてカスタマイズしていただければと思います。
from django.views.generic import TemplateView
from urllib import parse
class ConfirmReservationView(TemplateView):
# 省略
def get(self, request, *args, **kwargs):
referer = self.request.environ.get('HTTP_REFERER')
parsed_referer_url = parse.urlparse(referer)
if (not (self.request.get_host() == parsed_referer_url.netloc
and parsed_referer_url.path == reverse('hoge:reservation')))
or 'フォームの値のキー' not in self.request.session # セッションを使用し値を渡す場合はこの行を追加
or 'フォームの値のキー' not in self.request.POST: # POSTメソッドを使用し値を渡す場合はこの行を追加
return HttpResponseRedirect(reverse('hoge:top'))
return super().get(request, *args, **kwargs)
# 省略