らっちゃいブログ

日々の学びと気づきを発信するブログ

Django REST frameworkでAPIにアクセス権を実装する方法

スポンサーリンク

Django REST framework シリーズです。今回はアクセス権のお話をします。

Django REST framework を使ったことがないという方はこちらをどうぞ。

racchai.hatenablog.com

はじめに

API を実装する上で欠かせないのが、アクセス権の管理ですね。API 毎に実行可能かどうかをチェックする処理を入れるのは大変ですし、対応漏れも起きやすいです。かといって、自前で共通化するのも大変ですね。

Django REST framework では permission という概念でAPI毎にアクセス権を設定できるようになっていますので、本記事ではよくあるアクセス権を例に挙げて実装方法について紹介してみようと思います。

具体的な解説に入る前に、サンプルのAPIを作っておきます。

api.py

from rest_framework.generics import GenericAPIView
from rest_framework.response import Response

class SampleView(GenericAPIView):
    permission_classes = ()

    def get(self, request, format=None):
        return Response()

urls.py に以下を追加。

url(r'^sample', SampleView.as_view()),

SampleView に見慣れない permission_classes というフィールドが登場しましたが、Django REST framework ではここに Permission クラスを設定することでアクセス権を設定するようになります。

認証済みの場合のみアクセスさせたい

お決まりのやつですね。認証済みかどうかを検証するパーミッションについては、 Django REST Framework にて標準で用意されている IsAuthenticated がありますので、こちらを使うだけです。

from rest_framework.generics import GenericAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

class SampleView(GenericAPIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request, format=None):
        return Response()

permission_classes に IsAuthenticated を指定しました。これで認証済みでないと実行できないAPIとなります。

管理者のみアクセス可能

これもよくあるパターンですね。今回は特定のメールアドレス(admin@racchai.com)であれば管理者として判定するパーミッションを作成してみます。

作り方は簡単で、rest_framework.permissions.BasePermission を継承したクラスにて has_permission 関数を定義するだけです。has_permission 内でアクセス可能な条件を設定してあげれば、それだけでパーミッションクラスの完成となります。

from rest_framework.generics import GenericAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.permissions import BasePermission 

class IsAdmin(BasePermission):
    def has_permission(self, request, view):
        return request.user and request.user.email == 'admin@racchai.com'

class SampleView(GenericAPIView):
    permission_classes = (IsAdmin,)

    def get(self, request, format=None):
        return Response()

IsAdmin パーミッションを作成し、それを SampleView に設定しました。たったこれだけで、管理者しかアクセスできないAPIとなりました。

管理者のみ変更可能でそれ以外は閲覧のみさせたい

さきほど作成した IsAdmin パーミッションをさらに発展させてやるだけで実現できますね。新しいパーミッションIsAdminOrReadOnly として作成します。

from rest_framework.generics import GenericAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.permissions import BasePermission, SAFE_METHODS

class IsAdmin(BasePermission):
    def has_permission(self, request, view):
        return request.user and request.user.email == 'admin@racchai.com'

class IsAdminOrReadOnly(BasePermission):
    def has_permission(self, request, view):
        return request.method in SAFE_METHODS or IsAdmin().has_permission(request, view)

class SampleView(GenericAPIView):
    permission_classes = (IsAdminOrReadOnly,)

    def get(self, request, format=None):
        return Response()

    def post(self, request, format=None):
        return Response()

閲覧かどうかは、HTTP メソッドの種類で判別します。フレームワークの方で SAFE_METHODS(GET, HEAD, OPTIONS) が定義されているので、リクエストメソッドがそのどれかであれば True を返します。SAFE_METHODSでない場合は、IsAdmin パーミッションを評価することで実行可能かを判定するようになっています。

まとめ

簡単すぎてつまらない内容だったかもしれませんね。本当はパーミッションの仕組みでオブジェクトベースのアクセス権を設定することもできるのですが、長くなりそうなのでそれはまた別な機会にご紹介することにします。

それでは今回はこのへんで!