1.認証(Authentication) と 承認(Authorization) の違いについて
認証 ( Authentication )
サービス へ アクセス してきた ユーザー が 「本人であるかどうか」
を検証する。
承認 ( Authorization )
サービス へ アクセス してきた 認証済みユーザー が 「指定した リソース へ アクセスできるかどうか」
を制御する。
djangoのaccountを認証済みでないと実行できないapiにする(authorization)
class AccountViewSet(viewsets.ModelViewSet):
queryset = Account.objects.all()
serializer_class = AccountSerializer
permission_classes = [permissions.AllowAny]
permission_classes というフィールドが登場しましたが、Django REST framework ではここに Permission クラスを設定することでアクセス権を設定するようにする。(ここでは誰でもアクセスできる)
↓
class AccountViewSet(viewsets.ModelViewSet):
queryset = Account.objects.all()
serializer_class = AccountSerializer
permission_classes = [permissions.IsAuthenticated]
permission_classes に IsAuthenticated を指定した。これで認証済みでないと実行できないAPIにすることができた。
すると、、、
これで無事にセキュリティーレベルをあげることができました!
ここではアクセスするためにはtokenを登録する必要があるがそのAuthenticateの設定方法はsetting.py
で管理できる。
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication'
]
}
ここではトークンでアクセスできるようにしたいので'rest_framework.authentication.TokenAuthentication'
を追加した。
トークンの作成・取得方法
1.ユーザーを取得する
account = Account.objects.filter(id=14).first()
<output> < Account: 14>
account.user
<output> <User: 'ユーザー名'>
2.Tokenを作成・取得する
トークンの作り方
from rest_framework.authtoken.models import Token
token = Token.objects.create(user=...)
#取得の時はcreate→getに変える
print(token.key)
詳しくはdjango rest frameworkのドキュメントを参照。
https://www.django-rest-framework.org/api-guide/authentication/
get_queryset関数
AuthTokenでセキュリティーをあげたが、このままだとトークンを取得して一度ログインしてしまうとどのAccountの情報も取得できてしまうのでget_queryset関数をオーバーライドする
get_querysetとは?
get_querysetメソッドは主にListViewで使われますが、モデルインスタンスの一覧を返すメソッドです。例えばfilterメソッドで絞り込んだり、柔軟に一覧を取得したい場合はget_querysetメソッドを上書きしてそのように書きます。
class AccountViewSet(viewsets.ModelViewSet):
queryset = Account.objects.all()
serializer_class = AccountSerializer
# permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
queryset = self.queryset.filter(user=self.request.user)
return queryset
クエリセットを取得するget_querysetをオーバーライドする
to_representation関数
やりたいこと
Accountモデルのフィールドの中にトークンを追加したい。
def to_representation(self, value)
output = super().to_representation(value)
print(output)
#ターミナル上で確認する
return output
#ポストマンで確認する
↓
outputの辞書型にtokenというキーを追加する
上のコードで示すvalueはaccountのオブジェクトの中身と同じなのでその中にトークンのkeyとvalueを追加する
まず最初に、valueオブジェクトの型を確認するために
print(type(value))
を使う
type()とはオブジェクトの型を取得、確認
print(type('string'))
def to_representation(self, account):
print("hogehoge", type(account))
output = super().to_representation(account)
token = Token.objects.filter(user=account.user).first()
if not token:
token = Token.objects.create(user=account.user)
output['token'] = token.key
print(output)
return output
Django REST Framework:1つのAPIViewの中でリクエストメソッド毎にpermission_classesを分ける
やりたいこと
POSTの時にIsAuthenticationを外したい。なぜならアカウントがまだない時はトークンを作ることができないから
def get_permissions(self):
if self.request.method == 'POST':
return []
else:
return [permissions.IsAuthenticated()]
こうすることで、postメソッドの時はパーミッションが必要なく、getメソッドなどの時はIsAuthenticatedをパーミッションとして採用することができる。