6
7

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 1 year has passed since last update.

【Django】Auth機能とMessageフレームワークを使ってユーザーごとにアクセス権限を設ける方法

Last updated at Posted at 2023-05-16

概要

  • Djangoにて、ユーザー(グループ)ごとにページへのアクセス制限が設定し、アクセス権がない場合はフラッシュメッセージ(アラートみたいなポップアップ)を表示する実装を行いました。
    • デフォルトで実装されているauth機能と、メッセージフレームワークを利用します。
  • 本記事ではその実装方法を記載します。

前提

  • ディレクトリ構造は以下の通りです(関係ないものは省略)。
app
├── app
│   ├── settings.py
│   └── etc...
├── home
│   ├── views.py
│   ├── urls.py
│   ├── etc...
│   └── templates/pages
│       ├── base.html
│       └── home.html
└── sample
│   ├── views.py
│   ├── urls.py
│   └── templates/sample
│       ├── base.html
│       └── sample.html
└── sample2 etc...
  • home.htmlには、samplesample2のボタンがあり、それをクリックするとそれぞれのhtmlに飛べる状態になっています。今回のアクセス制限では、ボタンを押してもユーザーが該当のグループに属していない場合はホーム画面にリダイレクトされる実装を行います。
  • URLの直打ちでもルートにリダイレクトする設定になっています。

実装内容

①Auth機能でGroup作成&User追加
settings.pyの編集
urls.pyの編集
views.pyの編集
htmlテンプレートの編集

①Auth機能でGroup作成&User追加

  • Djangoの管理者アカウントでログインします。
  • Admin画面から「Group」を選択すると、以下の画面に遷移されるので、任意の名前でグループを作成します。今回は「writers」とします。

image.png

  • 次に、「Users」を選択して、任意のユーザー「hoge」を作成後、先ほどのグループに追加してあげます。

image.png

  • 追加が終わったら、SAVEで保存します。
  • これで、「writers」グループにユーザー「hoge」を追加することができました。

settings.pyの編集

  • まず、'django.contrib.messages''django.contrib.messages.middleware.MessageMiddleware'が記載されていることを確認します(デフォルトで記載されているはず)。
app/app/settings.py

INSTALLED_APPS = [
    # 他のアプリケーション
    'django.contrib.messages',
]

MIDDLEWARE = [
    # 他のミドルウェア
    'django.contrib.messages.middleware.MessageMiddleware'
]


MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
  • また、MESSAGE_STORAGEを追記します。これにより、メッセージはセッションストレージを使用して保存されるようになります。

urls.pyの編集

app/sample/urls.py
from django.urls import path
from . import views

urlpatterns = [
   path('', views.restricted_for_writers, name="sample"),
]
  • ルートURLに対してviews.restricted_for_writersビューを関連付けます。restricted_for_writers関数は、次のviews.pyで定義します。

views.pyの編集

app/sample/views.py
from django.shortcuts import render
from django.shortcuts import redirect
from django.contrib import messages

# Loginユーザーのみアクセス可
@login_required
def index(request):
    context = list_param(None)
    return render(request, 'sample/sample.html', context)

# 該当のグループに属している場合のみアクセス可
def for_groups_only(*group_names):
    def decorator(view_func):
        def wrapper(request, *args, **kwargs):
            user_groups = request.user.groups.values_list('name', flat=True)
            if any(group_name in user_groups for group_name in group_names):
                return view_func(request, *args, **kwargs)
            else:
                messages.warning(request, 'You do not have permission')
                return redirect('/')
        return wrapper
    return decorator

# このビューは 'writers' または 'checkers' グループに属するユーザーのみがアクセスできる
@for_groups_only('writers', 'checkers')
def restricted_for_writers(request):
    return render(request, 'sample/sample.html')

  • for_groups_onlyデコレータは、指定されたグループに属するユーザーのみがアクセスできるようにするためのデコレータです。
  • 「writers」はDjango Authで作成したグループ名です。

htmlテンプレートの編集

app/home/templates/pages/base.html
# 略

<body>

{% if messages %}
<ul class="messages_ul">
  {% for message in messages %}
    <li class="alert{% if message.tags %} alert-{{ message.tags }}{% endif %}" role="alert">{{ message }}</li>
  {% endfor %}
</ul>
{% endif %}

# 略

完成。いざ検証!

  • 作成したユーザー「hoge」でログインしている状態で、アクセス権限のないURLへ飛ぶボタンをクリックすると、ホーム画面に戻って以下のメッセージがページ上部に表示されることを確認できました。

image.png

  • 今回はwarningを指定していますが、他にも以下のような項目があります。
debug
info
success
warning
error

備考

  • ちなみに、user_passes_testデコレータを使った実装方法もあります。ただし、この場合、リダイレクト先としてlogin_url='/'と指定しているので、アクセス権限がない場合はルートURL('/')に飛んでしまい、メッセージの表示ができませんでした。関数の中にif not...と記載してメッセージのコードを記載しても、リダイレクトが優先されてしまうようです。メッセージが不要な場合は以下の方が簡潔に実装できます。(このやり方で、メッセージも表示できる方法をご存知の方いましたらぜひ教えてください)
views.py
from django.shortcuts import render
from django.contrib.auth.decorators import user_passes_test

@user_passes_test(lambda u: u.groups.filter(name='writers').exists(), login_url='/')
def restricted_for_writers(request):
    return render(request, 'sample/sample.html')
  • 以上、いろいろやってみた結果、Auth機能とMessageフレームワークを使ったアクセス権限を設定する方法を実現できました。
  • 今回の実装方法では、ユーザーによってはアクセスできないボタンがホーム画面に出る状態です。ユーザーごとにボタンの表示が変わる方がセキュリティ的には好ましいと思うので、別途その実装もしてみようと思います。
  • また、「アクセス権限がありません」というページを準備して、「ホーム画面に戻る」みたいなボタンを下部に設置するのも親切かもしれませんね。
6
7
0

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
6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?