ログアウト:GETまたはPOST?


433

この質問は、GETまたはPOSTを一般的にいつ使用するかに関するものではありません。これは、Webアプリケーションのログアウトを処理するために推奨される方法です。一般的な意味でのGETとPOSTの違いに関する多くの情報を見つけましたが、この特定のシナリオに対する明確な答えは見つかりませんでした。

実用主義者として、私はGETを使用する傾向があります。GETの実装はPOSTよりもはるかに簡単だからです。単純なリンクをドロップするだけで完了です。これは、少なくとも頭のてっぺんから、私が考えることができる大多数のWebサイトに当てはまるようです。Stack Overflowでも、GETを使用してログアウトを処理します。

私が躊躇しているのは、一部のWebアクセラレータ/プロキシがページ内で見つかったすべてのリンクに移動して取得することでページをプリキャッシュする(古い)引数であり、ユーザーがクリックしたときにユーザーがより迅速に応答するようにします。これがまだ当てはまるかどうかはわかりませんが、これが当てはまる場合、理論的には、これらのアクセラレータのいずれかを使用しているユーザーは、ログインするとすぐにアプリケーションから追い出されます。彼女はそれをクリックしなかった場合でも、リンク。

これまでに読んだことはすべて、POSTは「破壊的なアクション」に使用する必要があることを示唆していますが、アプリケーションの内部状態を変更しないアクション(クエリなど)はGETで処理する必要があります。これに基づいて、ここでの本当の質問は次のとおりです。

アプリケーションからのログアウトは破壊的なアクションと見なされますか/それはアプリケーションの内部状態を変更しますか?


さて、初めてサイトにアクセスし、ログアウトリンクが存在しない場合、ログインするとログアウトされます。ログアウトURLはすでにキャッシュされているため、2回目にログインした後は問題ありません。しかし、まともなアクセラレータがほとんどのログアウトURLを除外できると想定できます。
HyperCas 2010

2
HyperCas、ログアウトURLを除外するアクセラレーターは、私が検討していた理論であり、質問を投稿することにした理由の1つです。アクセラレータのロジックだけを信頼するのは少し気が進まないので、ある日、くだらないアクセラレータを使用しているユーザーが、ログインできないと不平を言っています。彼らが標準に従っているか、そのような標準が存在するかどうか知っていますか?
Daniel Liuzzi

フォームを自動的に送信したアクセラレータは(たとえば)マルウェアIMOになります...アクセラレータが自動的にフォームを送信することを考えるのはまったく非論理的です。Googleにアクセスするとします。どのようにして検索フォームを送信できますか?マルウェアは予測不可能であり、ルールに従っていないため、マルウェアを説明することはできません。
Alex

3
@AlexW-あなたは私の質問を誤解したと思います。私が提案したアクセラレータシナリオは、POSTではなくGETを使用するときに起こり得る問題を示すことです。そのため、投稿するフォームはなく、どのアクセラレータでも問題が発生しないプレーンリンクのみです。
Daniel Liuzzi

1
もう遅すぎると思いますが、アレックス、それはダニエルが尋ねていることではありません。ユーザーがログアウトリンクをクリックし、アクセラレータがアプリケーションにヒットせずにキャッシュされたログアウトページを返す場合、ユーザーはログインしたままになると彼は言っています。マルウェアとは関係ありませんが、FYIでユーザーエージェント文字列をチェックしても修正されませんとにかく何でも。
ロブ・グラント

回答:


474

を使用しPOSTます。

2010年には、使用GETはおそらく許容できる回答でした。しかし、今日(2013年)、ブラウザは、次にアクセスすると "考える"ページをプリフェッチします。

StackOverflowの開発者の1人がこの問題についてTwitterで話しています。

GETリクエストをログオフしてくれた私の銀行と、便利なURLプリフェッチを行ったChromeチームに感謝します。-Nick Craver(@Nick_Craver2013年1月29日

面白い事実:StackOverflowはGETを介してログアウトを処理するために使用されていましたが、現在は使用されていません。


2
このアップデートをありがとう、デイブ。私がSOがログアウトをPOSTに切り替えたことにも気づかなかったし、正直に言って、Chromeにプリフェッチが組み込まれている手掛かりはありませんでした。最後に、あなたが引用したツイットは、私の質問と私の疑いを確認します。私はあなたの回答に投票し、承認された回答にします。
Daniel Liuzzi、2013

4
私のブラウザでは、Stackoverflowのログアウトは<li> <a href="https://stackoverflow.com/users/logout">ログアウト</a> </ li>のように見えます。これはPOSTではなくGETです
boatcoder

9
@ Mark0978、リンクをクリックします。
デビッドマードック

2
面白い。これはおそらく、私の最もお気に入りの機能の1つです。ログアウトすると、確信があるかどうかを尋ねられます。プリフェッチによってログアウトされないようにすると思いますが、Amazon、Ebay、Gmailはすべて、ログアウトと実際のログアウトイベントの間にトリックページが表示されずにGETを使用してログアウトします。ページの間にあると、多くの人がログアウトしたと誤解してしまうと思います。SOでの問題は最小限で、お金もかからず、すべての99%がとにかく公開されています。
ボートコーダー2013

7
@Red HTTP / 1.1標準によれば、これはサーバーの障害であり、ブラウザーの障害ではありません。GETは、サーバー側に副作用がないと予想されます。この規格には、「ユーザーが副作用を要求しなかったため、副作用について責任を負わせることはできない」とさえ書かれています。
eyuelt 2014

45

RESTではセッションはないはずなので、破壊するものはありません。RESTクライアントはすべてのリクエストで認証を行います。ログインまたはログアウト、それは単なる幻想です。

あなたが本当に求めているのは、ブラウザがすべてのリクエストで認証情報を送信し続けるかどうかです。

間違いなく、アプリケーションがログインしているように見える場合は、JavaScriptを使用して「ログアウト」できるはずです。往復は必要ありません。


フィールディング論文- セクション5.1.3

クライアントからサーバーへの各要求には、要求を理解するために必要なすべての情報が含まれている必要があり、サーバーに格納されているコンテキストを利用することはできません。したがって、セッション状態は完全にクライアントで保持されます


1
私は実際にはこれを知りませんでした。次に、FormsAuthenticationでASP.NET MVCを使用しており、セッションに依存しているため、私のアプリはそれほどRESTfulにならないと思います
Daniel Liuzzi

18
しかし実際には、httponly一部のxssリスクを防ぐために属性でマークされたcookieにログイン情報が保持されます。つまり、サーバーからのみリセットできます(cookieを手動でクリアしない限り)
Remus Rusanu

6
ユーザーの場合と同様に「手動」はブラウザ設定に移動し、「Cookieをクリア」オプションを選択します。Webサイトから「ログオフ」するための許容できる方法はほとんどありません。
Remus Rusanu 2010

1
@Remus Ahhh、輝かしいWebブラウザーがWebアプリの作成をいかに苦痛にするか。
Darrel Miller、

1
@DarrelMillerはい、サーバー側でJWTを取り消さないことはセキュリティ上の脆弱性です。トークンがサーバーに保存されていない場合でも、ユーザーがログアウトしたり、パスワードを変更したり、役割を変更したり、終了したりすると、悪用を防ぐために(少なくとも期限が切れるまで)トークンをブラックリストに登録する必要があります。
java-addict301

38

GETここで悪用される可能性のある方法の1つは、人(おそらく競合他社:) src="<your logout link>"がインターネット上の任意の場所にイメージタグを配置し、サイトのユーザーがそのページに遭遇した場合、無意識のうちにログアウトされることです。


4
いいえ、これは正しくありません。ログアウトリンクは、別のドメインからではない正しいCookieデータが送信された場合にのみ機能します。また、セッションIDがURLに格納されている場合でも、セッションごとに変更されるため、機能しません。
リチャードH

4
うわー、そんなことは考えたことがない!そこで、GETを使用しないもう1つの理由と、GETを使用しない理由がもう1つあります。いまいましい、今私は自分の投稿にstackoverflow.com/users/logout "image"も含めて、何が起こるかを見たいと思っています:-D
Daniel Liuzzi

24
src =は単純なブラウザー要求であり、サーバー側からではなくクライアントから送信されます。すべてのCookieを保持し、ユーザーIPから取得されます。これが、広告追跡ピクセルが機能する理由です。このようなエクスプロイトを特定する唯一の方法は、リファラーをチェックすることです。
raveren

12
SuperLogout.comはそれを正確に実行し(/logout非表示画像にURLをロードします)、機能します。
Dan Dascalescu

9
re:SuperLogout ...なぜそれをクリックしたのかわかりません。
MIライト

21

正確には、GET / POST(または他の動詞)は(URLによってアドレス指定された)いくつかのリソースに対するアクションです。そのため、通常はリソースの状態に関するものであり、アプリケーションの状態に関するものではありません。したがって、本当の意味で、のようなURLが必要[host name]\[user name]\sessionです。その場合、「DELETE」はログアウトアクションの正しい動詞になります。

[host name]\bla bla\logout実際にはRESTフルウェイ(IMO)ではなくURLとして使用しているので、GET / POSTの正しい使用についてなぜ議論するのでしょうか。

もちろん、アプリケーションでログアウトURLにGETも使用します:-)


2
その場合、ユーザーは常に自分のセッションからログアウト(削除)するため、URLに[ユーザー名]の部分を含める必要はないと思われます。決して他のユーザーではない:-)
Daniel Liuzzi

1
本当にそうではありません-セッションはリソースであり、それを削除したいと言っています。したがって、すべてのセッションを均一にアドレス指定するには、URLの一部としてユーザー名が必要です。あなたの主張は、[フォトギャラリー] \ picturesにPUTアクションを発行することは、写真に追加することを意味する([フォトギャラリー] \ [ユーザー名] \ picturesで入手可能)と同じくらい良いです。さまざまなリソースを明示的に対処する必要があります。それに暗黙的な要素を含めることはできません。このサイトでは、他のユーザーがあなたのギャラリーに写真を追加することを許可しているかもしれません-誰かのセッションを殺すことができるスーパーユーザーがいるのと同じように、それはアクセス制御の一部です。
VinayC 2010

1
哲学的に言えば、セッションや写真を「リソース」と呼ぶことができますが、現実的にはそれらを同じように扱うことはしません。セッションは常に本質的に現在のユーザー(したがって、セッションという名前)に制限されており、少なくともASP.NETでは、別のユーザーのセッションにアクセスする方法はありません。アプリケーション開発者でさえ、すべてのアクティブなセッションを直接列挙する方法がなく、セッションを個別に強制終了する手段もありません。アプリケーションを再起動してすべてのセッション(InProc)を強制終了することもできますが、そのアクセス制御は呼び出しません。URLは別として、問題はまだ残っています:GETまたはPOST?
Daniel Liuzzi

リソース、つまりそのアドレス(URL)はRESTの重要な部分です。したがって、私が言ったようにURLを選択した場合、DELETEは正しい単語になります-GETまたはPOSTではありません。また、ASP.NETに限定している場合でも、セッションを列挙し、必要に応じて他のセッションを強制終了する方法を提供できるカスタム状態プロバイダーを常に使用できます。すぐに使えるインプロセスセッションの場合、global.asaxをいじると、機能が提供されます。そのような機能が必要かどうかというのは、本当に問題です。まれなニーズのために、人々は人々をサイトから追い出すためにウェブサイトを再スタートする傾向があります。
VinayC 2010

これは私にとって最も理にかなっています。Web APIにセッションルートを与え、DELETEを呼び出します。../sessionまたは../session/currentである。Thankx @VinayC
サイモンフーパー

16

ログアウトしてもアプリケーション自体には何の影響もありません。アプリケーションに関連するユーザーの状態を変更します。この場合、あなたの質問は、このアクションを開始するためにユーザーからコマンドをどのように開始する必要があるかに基づいているようです。これは「破壊的なアクション」ではないため、セッションは破棄または破棄されますが、アプリケーションもデータも変更されないため、両方の方法でログアウト手順を開始することはできません。投稿は、ユーザーが開始したアクション(たとえば、ユーザーが[ログアウト]をクリック)で使用する必要があります。一方、getは、アプリケーションが開始したログアウト用に予約できます(例:潜在的なユーザー侵入を検出する例外により、ログアウトGETを使用してログインページに強制的にリダイレクトされます。 )。


面白い; このように考えたことはありません。+1。
ストレッジャー2010

これはおそらくアプリケーションに依存する可能性がありますが(ある種の「カスケード削除」動作)、その通りです。
Andres Jaan Tack 2010

@JoelEthertonありがとうJoel、私はいつ正しい答えに到達するのか疑問に思っていた答えを読んでいました。:)
キリル・フックス2015年

4
ログアウトの状態が変わるため、混乱を招きます。POSTは状態を変更する動詞です。GETは、ステートレスデータを取得するためのものです。POSTリクエストにはペイロードが含まれていると予想されるため、混乱を招きます。以下に示すように、DELETEはセッションオブジェクトに対して最も適切です。
マイケルコール

1
@MichaelCole:POSTとGETの間の困難さの表現に同意します。ただし、DELETE動詞の使用には同意しません。DELETEはリソースを処理するためのものであり、この意味でセッションはリソースではありません。削除できる場合は、PUTもできるようにしてください。
Joel Etherton、2015

16

こんにちは私の観点では、ログインするときにユーザー名/パスワードを確認し、それらが一致する場合はログイントークンを作成します。

CREATトークン=>メソッドPOST

ログアウトするとき、トークンを破壊するので、私にとって最も論理的な方法はDELETEであるべきです

DELETEトークン=>メソッドDELETE


4
興味深い角度。
Drumbeg 2018年

1
私は、Spring Boot RESTアプリケーションでその方法を使用しています。
Please_Dont_Bully_Me_SO_Lords 2018年

1
意味的に正しい。同意します...
DAG

1

事前キャッシュのシナリオは興味深いものです。しかし、私はSOを含む多くのサイトがこれについて心配していなければ、多分あなたもそうすべきではないと思います。

または、リンクをJavaScriptで実装できますか?

編集:私が理解しているように、技術的には、GETは読み取り専用リクエスト用であり、アプリケーションの状態を変更しないものでなければなりません。POSTは、状態を変更する書き込み/編集リクエスト用です。ただし、他のアプリケーションの問題では、一部の状態変更要求に対してPOSTよりもGETを優先する場合があり、これには問題がないと思います。


ありがとう。DBの状態を変更することはないだろうが、セッション状態がでしょう。私が目にする唯一の問題は、ユーザーが追い出されるという質問で述べたものです。非破壊的ですが、かなり迷惑です。私は通常、「大物がそれをするなら、それは大丈夫だろう」というマントラも通します。私は他の人がこれについてどのような意見を持っているのか知りたいだけでした。
Daniel Liuzzi

0

Webアプリケーションでログアウトスクリプトを使用してセッションを中止する場合は、通常どちらも必要ありません。通常、破棄したいセッションに固有のセッション変数があります。


「ログアウトスクリプト」について詳しく説明していただけませんか?クッキーの有効期限の設定を参照している場合、私はよく分からない(手動でログアウトユーザーをさせるの方法の必要性がなくなるわけではありません。)
ダニエル・リウッツィ

ログアウトスクリプトは、それを呼び出しているユーザー(実際にはブラウザ)のセッションを終了します。ASP.netでは、セッションは破棄できるサーバー側オブジェクトです。PHPにも同様のシステムがあります。そのブラウザーはセッションを終了するスクリプトを呼び出すので、終了するスクリプトが既にわかっているため、POST変数またはGET変数の必要がなくなります。
Rob

1
はい、私は今あなたを取得します。私は既にスクリプト、具体的にはFormsAuthentication.SignOut()を用意していますが、私の質問は、GETまたはPOSTのようにスクリプトを呼び出す方法についてです。
Daniel Liuzzi

ああ、あなたはフォームのURLを持っていますか?情報を渡さなくてもかまいません。起こり得る最悪の事態は、誰かが手動でスクリプトを開き、自分自身をログアウトすることです。必要がなければフォームフィールドにすることすらしません。スクリプトへのリンクも機能します。スクリプトに情報を送信する場合は、おそらくユーザーに情報を表示しないように(ページソースを表示しない限り)POSTを実行し、更新するとブラウザから警告が表示されます(ページの有効期限が切れた)、望ましい場合があります。
Rob

0

最近私はGETを使用してログアウトするプロジェクトに取り組んでいました以下はNodejs Expressのコードで、完全に正常に動作します

あなたのrouter.js

const express = require("express");
router.get("/signout", signout);

あなたのcontroller.js

exports.signout  = (req, res) => {
        res.clearCookie('t'); //clearing cookie, which is 
            //assign to the user during sign in.          
            res.json({message : 'Signout success'});   
        };

-2

ログアウト(ユーザーのアクセス許可の昇格)がどのように破壊的なアクションであるかはわかりません。これは、「ログアウト」アクションはすでにログインしているユーザーのみが使用できるようにする必要があるためです。それ以外の場合は廃止されます。

ブラウザのCookieに含まれるランダムに生成された文字列は、すべてユーザーセッションを表しています。それを破壊する方法はたくさんあるので、効果的にログアウトするのは訪問者へのサービスにすぎません。


2
wgetプライベートWikiで正しいセッションCookieを使用するスパイダーモードでは、実際に1回実行する必要がありました。もちろん、最初にクロールされたURLの1つはでした/logout
ヘルギ

5
SuperLogout.comにアクセスして、/logoutページへのGETリクエストが実際にどの程度破壊的かを確認してください。たとえば、Gmailに再度ログインし、チャットに再度ログインし、スクロールしたハングアウトの会話で自分の場所を見つける必要があります。これはGoogle.com専用です。
Dan Dascalescu
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.