ログアウトはGETまたはPOSTにする必要がありますか?
1. 概要
従来のWebアプリケーションでは、通常、ログインするには、認証のためにサーバーにユーザー名とパスワードを送信する必要があります。 これらの要素は理論的にはGETリクエストのURLパラメータである可能性がありますが、POSTリクエストにカプセル化する方が明らかにはるかに優れています。
ただし、機密情報を送信する必要がないため、GETリクエストを介してログアウトできるようにする必要がありますか?
このチュートリアルでは、この設計上の考慮事項のさまざまな側面を見ていきます。
2. サーバーサイドセッション
サーバー側のセッションを管理する場合、それらのセッションを破棄するためにエンドポイントを公開する必要があります。 GETメソッドは単純であるため、使用したくなるかもしれません。 もちろん、これは技術的には機能しますが、望ましくない動作を引き起こす可能性があります。
Webアクセラレータのように、ユーザーのGETリンクをプリフェッチするプロセスがいくつかあります。 プリフェッチの目的は、ユーザーがそのリンクをたどるとすぐにコンテンツを提供することです。これにより、ページの読み込み時間が短縮されます。 これらのプロセスは、 GETリンクがコンテンツを返すためだけのものであり、何かの状態を変更するためのものではないことを前提としています。
ログアウトをGETリクエストとして公開し、それをリンクとして提示すると、これらのプロセスは、ページ上のリンクをプリフェッチしようとしているときに、誤ってユーザーをログアウトさせる可能性があります。
たとえば、JavaScriptによって決定されるなど、ログアウトURLが静的に利用できない場合、これは問題にならない可能性があります。 ただし、 HTTP / 1.1 RFC は、GETメソッドはコンテンツを返すためにのみ使用する必要があり、ユーザーはGETリクエストの副作用について責任を負わないことを明確に述べています。 可能な限り、この推奨事項に従う必要があります。
対照的に、RFCは、POSTメソッドをデータ(セッションまたはセッションID)をデータ処理プロセス(ログアウト)に送信できるメソッドとして説明しています。 これは、私たちが達成しようとしていることのより適切な説明です。
2.1. 春のセキュリティ
デフォルトでは、SpringSecurityではログアウト要求のタイプがPOSTである必要があります。 ただし、 CSRF保護を無効にすると、SpringにGETログアウトリクエストを使用させることができます。
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
...
}
3. ステートレスREST
ステートレスRESTセッションを管理する場合、「ログアウト」の概念が変わります。 ステートレス環境では、すべてのリクエストにセッション全体が含まれます。 したがって、Javascriptを使用してセッションを破棄するだけで、あらゆる種類のリクエストを送信するのではなく、「ログアウト」することができます。
ただし、セキュリティ上の理由から、取り消されたJWTをブラックリストに登録するには、サーバーにログアウトアクションを通知する必要があります。 これにより、「ログアウト」後にセッションが使用されるのを防ぎます。
ステートレス環境でも、ログアウト時にサーバーにリクエストを送信する必要があります。このようなリクエストの目的はコンテンツを取得することではないため、GETを介して行うことはできません。 代わりに、ログアウトする明示的な意図を持って、セッションをサーバーにPOSTする必要があります。
4. 結論
この短い説明では、ログアウトをGETにするかPOSTにするかという一般的な設計上の質問について簡単に説明しました。
この問題のさまざまな側面を検討しました。
- 意味的には、GETリクエストはステートフルな副作用をもたらすべきではありません
- プリフェッチリンクを含む、ユーザーがブラウザで実行している可能性のあるプロセスがあります。 GETを介してログアウトが発生した場合、プリフェッチプロセスにより、ログイン後にユーザーが誤ってログアウトされる可能性があります。
- ステートレスセッションでも、ログアウトイベントをサーバーに報告する必要があります。これはPOSTリクエストを介して実行する必要があります。