JWTを使用しているときにログアウトするのが良いかどうかを尋ねたいと思います。ログインするには、ユーザー名とパスワードを使用してPOSTリクエストを送信し、目的のトークン(localStorageに保存)を取得します。これにより、もちろん、トークンを必要とするビューにさらにリクエストを送信できます。
しかし、どのようにユーザーをログアウトすればよいのかわかりません。 localStorageをクリアできますが、トークンは引き続き使用できます。
トークンを無効にできないので、トークンを更新する必要があるかどうかを尋ねたいと思います。
JWTトークンを削除した後でも、有効期限が切れるまで一定期間有効なトークンのままです。 JWTはステートレスです。したがって、ログアウトを処理してトークンを無効にする場合は、データベースまたはメモリキャッシュに保持して、無効な(ブラックリストに登録された)トークンを保存する必要があります。次に、トークンがブラックリストに登録されているかどうかを確認するための新しい権限を追加する必要があります。
class BlackListedToken(models.Model):
token = models.CharField(max_length=500)
user = models.ForeignKey(User, related_name="token_user", on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now=True)
class Meta:
unique_together = ("token", "user")
class IsTokenValid(BasePermission):
def has_permission(self, request, view):
user_id = request.user.id
is_allowed_user = True
token = request.auth.decode("utf-8")
try:
is_blackListed = BlackListedToken.objects.get(user=user_id, token=token)
if is_blackListed:
is_allowed_user = False
except BlackListedToken.DoesNotExist:
is_allowed_user = True
return is_allowed_user
有効期限が切れた後、ブラックリストリストからトークンを削除できます。
トークンの作成後に手動で期限切れにすることはできません。したがって、セッションの場合のように、サーバー側でJWTを使用して実際にログアウトすることはできません。
JWTはステートレスです。つまり、必要なものはすべてペイロードに保存し、すべてのリクエストでDBクエリの実行をスキップする必要があります。ただし、クライアント側からトークンをクリーンアップした場合でも、トークンの自動有効期限を待つことができない厳密なログアウト機能を計画している場合は、ステートレスロジックを無視して、いくつかのクエリを実行する必要があります。だから解決策は何ですか?
トークンに適切な有効期限を設定する
ログアウト時にクライアント側から保存されたトークンを削除します
許可されたすべてのリクエストでブラックリストに対して提供されたトークンをクエリします
有効でなく、まだ有効期限が切れていないすべてのトークンの「ブラックリスト」。トークンの有効期限が切れるまでの残り時間に設定されるドキュメントに対してTTLオプションがあるDBを使用できます。
Redisはblackblistに適したオプションであり、リストへの高速メモリアクセスを可能にします。次に、許可されたすべてのリクエストで実行されるある種のミドルウェアで、提供されたトークンがブラックリストにあるかどうかを確認する必要があります。もしそうなら、あなたは無許可のエラーを投げるべきです。そうでない場合は、手放すとJWT検証がそれを処理し、有効期限が切れているか、まだアクティブであるかを識別します。
発行するすべてのJWTには有効期限が設定されている必要があるため、ユーザーをログアウトするときは常に、ローカルストレージCookieからjwtトークンを削除する必要があります。
ただし、トークンは引き続き使用できます。
上記の行の意味はわかりませんが、localstorageとcookieからトークンをクリアした後も、トークンがユーザーに利用可能であるかどうかについて心配する必要はありません。どちらの場合も、有効期限後に無効になるためです。