セッションは本当にRESTfulnessに違反していますか?


491

RESTful APIでのセッションの使用は本当にRESTfulnessに違反していますか?私は多くの意見がどちらの方向にも進んでいるのを見てきましたが、セッションがRESTなしであると思いません。私の視点から:

  • 認証はRESTfulnessで禁止されていません(そうでなければRESTfulサービスではほとんど使用されません)
  • 認証は、リクエストで認証トークンを送信することで行われ、通常はヘッダー
  • この認証トークンは何らかの方法で取得する必要があり、取り消すことができます。その場合、更新する必要があります
  • 認証トークンはサーバーによって検証される必要があります(そうでなければ、認証ではありません)

では、セッションはこれにどのように違反しますか?

  • クライアント側、セッションはcookieを使用して実現されます
  • Cookieは単なる追加のHTTPヘッダーです
  • セッションCookieはいつでも取得して取り消すことができます
  • セッションCookieは、必要に応じて無限の寿命を持つことができます
  • セッションID(認証トークン)はサーバー側で検証されます

そのため、クライアントにとって、セッションCookieは、他の独自のヘッダーのCookie代わりにヘッダーを使用することを除いて、他のHTTPヘッダーベースの認証メカニズムとまったく同じAuthorizationです。サーバー側のCookie値にセッションがアタッチされていない場合、なぜ違いが生じるのでしょうか?サーバー RESTfulに動作する限り、サーバー側の実装はクライアントに関係する必要はありません。そのため、Cookie自体はAPIをRESTlessにすべきではなく、セッションは単にクライアントへのCookieです。

私の仮定は間違っていますか?セッションCookieをRESTレスにするものは何ですか?


5
私はここでその正確な問題を取り上げました:stackoverflow.com/questions/1296421/rest-complex-applications/...
ウィルアルトゥング

5
これに追加して、認証にのみセッションを使用している場合は、提供されたヘッダーを使用しないのはなぜですか?そうでない場合、セッションを会話の他の状態に使用していると、RESTのステートレス制約に違反しています。
Will Hartung、

2
@ありがとう。ユーザーが送信したデータを一時的に保存するセッションについて話しているようですが、私の場合は、認証の実装の詳細として話しているだけです。これが不一致の原因なのでしょうか?
だます

3
@deceze私の唯一のポイントは、ヘッダーを使用して認証トークンを表す場合、HTTPは一般的なCookieに加えてヘッダーを提供するということです。それで、それを使用せず、それで得られる無料のセマンティクスを維持してください(ペイロードを見ると、それに割り当てられた認証トークンがあることがわかります)。
Will Hartung、

7
もちろん、独自のヘッダーを作成したり、認証トークン用の他のヘッダーを乗っ取ったりしてはどうでしょう。X-XYZZYヘッダーを使用します。構文は正しいですか?ヘッダーは情報を伝えます。「誰もが」Authヘッダーの目的を知っているため、AuthorizationヘッダーはCookieよりも「自己文書化」されています。JSESSIONID(または何でも)が表示されるだけの場合、想定を行うことはできず、さらに悪いことに、誤った想定(彼はセッションに他に何を格納しているか、他に何に使用されているかなど)を行うことができます。コードAq12hsgで変数に名前を付けますか?いいえ、もちろん違います。ここでも同じことが当てはまります。
Will Hartung、

回答:


299

まず、いくつかの用語を定義しましょう:

  • RESTful:

    このセクションで説明するREST制約に準拠するアプリケーションを「RESTful」として特徴付けることができます。[15] サービスが必要な制約に違反している場合、RESTfulとは見なされません。

    ウィキペディアによると。

  • ステートレス制約:

    次に、クライアントとサーバーの相互作用に制約を追加します。セクション3.4.3(図5-3)のクライアントステートレスサーバー(CSS)スタイルのように、通信は本質的にステートレスである必要があります。サーバーには、リクエストを理解するために必要なすべての情報が含まれている必要があり、サーバーに保存されているコンテキストを利用することはできません。したがって、セッション状態は完全にクライアントで保持されます。

    フィールディングの論文

したがって、サーバー側のセッションはRESTのステートレスな制約に違反しているため、RESTfulにも違反しています。

そのため、クライアントにとって、セッションCookieは、Authorizationまたはその他の独自のヘッダーの代わりにCookieヘッダーを使用することを除いて、他のHTTPヘッダーベースの認証メカニズムとまったく同じです。

セッションCookieを使用すると、クライアントの状態をサーバーに保存するため、リクエストにはコンテキストが含まれます。ロードバランサーと別のサービスインスタンスをシステムに追加してみましょう。この場合、サービスインスタンス間でセッションを共有する必要があります。そのようなシステムを維持および拡張することは難しいので、スケーリングがひどいです...

私の意見では、クッキーには何の問題もありません。Cookieテクノロジーはクライアント側の保存メカニズムであり、保存されたデータはすべてのリクエストによってCookieヘッダーに自動的に添付されます。そのようなテクノロジーに問題があるREST制約については知りません。したがって、テクノロジー自体には問題はありません。問題はその使用法です。フィールディングは、 HTTP Cookieが悪いと考える理由についての小節を書きました

私の視点から:

  • 認証はRESTfulnessで禁止されていません(そうでなければRESTfulサービスではほとんど使用されません)
  • 認証は、リクエストで認証トークンを送信することで行われ、通常はヘッダー
  • この認証トークンは何らかの方法で取得する必要があり、取り消すことができます。その場合、更新する必要があります
  • 認証トークンはサーバーによって検証される必要があります(そうでなければ、認証ではありません)

あなたの視点はかなり堅実でした。唯一の問題は、サーバー上で認証トークンを作成するという概念にありました。その部分は必要ありません。必要なのは、ユーザー名とパスワードをクライアントに保存し、すべてのリクエストで送信することです。HTTP基本認証と暗号化された接続以外にこれを行う必要はありません。

図1.-信頼できるクライアントによるステートレス認証

  • 図1.-信頼できるクライアントによるステートレス認証

すべてのリクエストを認証する必要があるため、処理を高速化するためにサーバー側にメモリ内の認証キャッシュが必要になる可能性があります。

これはあなたが書いた信頼できるクライアントでかなりうまく動作しますが、サードパーティのクライアントはどうですか?ユーザー名とパスワード、およびユーザーのすべての権限を持つことはできません。そのため、サードパーティのクライアントが特定のユーザーに対して持つことができる権限を個別に保存する必要があります。そのため、クライアント開発者はサードパーティのクライアントを登録して一意のAPIキーを取得でき、ユーザーはサードパーティのクライアントに権限の一部へのアクセスを許可できます。名前やメールアドレスを読んだり、友達をリストしたりするのと同じように...サードパーティのクライアントを許可した後、サーバーはアクセストークンを生成します。これらのアクセストークンは、次のように、サードパーティのクライアントがユーザーによって付与された権限にアクセスするために使用できます。

図2.-サードパーティのクライアントによるステートレス認証

  • 図2.-サードパーティのクライアントによるステートレス認証

したがって、サードパーティのクライアントは、信頼できるクライアントから(またはユーザーから直接)アクセストークンを取得できます。その後、APIキーとアクセストークンを使用して有効なリクエストを送信できます。これは、最も基本的なサードパーティの認証メカニズムです。実装の詳細については、OAuthなどのサードパーティの認証システムのドキュメントをご覧ください。もちろん、これはより複雑で安全です。たとえば、サーバー側ですべてのリクエストの詳細に署名し、リクエストとともに署名を送信できます。実際の解決策は、アプリケーションのニーズによって異なります。


5
はい、あなたは完全に正しいです。私がこの質問を投稿して以来、私はそれを見て回ってきました。技術的な詳細で見ると、セッションCookieは特別なものではありませんが、それは木の森を失っています。素晴らしいチャートのためにあなたの答えを受け入れました。;)
deceze

1
OK、私は再考しました、RESTサービスの応答は承認に依存するべきではないので、最初の2つのソリューションは100%正常であり、サービスが要求を許可するかどうかを決定するためだけに情報を使用する場合、他のソリューションは大丈夫だと思いますない。したがって、ユーザー権限は現在のリソースの表現に影響を与えるはずです。
inf3rno 2013

1
表現の権限の依存関係に関する質問を作成します。適切な解決策が得られたらすぐに、この答えを拡張します。
inf3rno 2013

3
@ inf3rno、完全にRESTfulなサービスは、従来の方法で実装されている方法では、認証のためにセッションCookieに依存できないことは事実です。ただし、サーバーに後で必要になるすべての状態情報がCookieに含まれている場合は、Cookieを使用して認証を実行できます。公開鍵と秘密鍵のペアで署名することにより、改ざんからCookieを保護することもできます。以下の私のコメントを参照してください。
jcoffland

3
クライアント側でパスワードを保存し、すべてのリクエストで送信する必要があるコメントを誰もが受け入れるように見える理由がわかりません。これは非常に悪い習慣であり、顧客の機密データを危険にさらします。ハッシュ化されていないパスワード(パスワードを何度も送信するために必要です)は、どこにも保存しないでください。これを受け入れると、ほとんどの認証システムと同じようにトークンを使用します。この場合、トークンリポジトリのスケーリングに使用するメカニズムは、セッションのスケーラビリティとほとんど同じスケーラビリティの懸念があります。
lvoelk

334

まず第一に、RESTは宗教ではないので、そのように取り組まれるべきではありません。RESTfulサービスには利点がありますが、アプリケーションにとって意味のある範囲でのみRESTの原則に従う必要があります。

つまり、認証とクライアント側の状態はRESTの原則に違反していません。RESTは状態遷移がステートレスであることを要求しますが、これはサーバー自体を参照しています。基本的に、RESTはすべてドキュメントに関するものです。ステートレスの背後にある考え方は、サーバーはクライアントではなくステートレスであるということです。同じ要求(同じヘッダー、Cookie、URIなど)を発行するクライアントは、アプリケーションの同じ場所に移動する必要があります。Webサイトがユーザーの現在の場所と、このサーバー側のナビゲーション変数を更新することによって管理されたナビゲーションを格納した場合、RESTに違反します。同じ要求情報を持つ別のクライアントは、サーバー側の状態に応じて別の場所に移動されます。

GoogleのWebサービスは、RESTfulシステムの素晴らしい例です。ユーザーの認証キーを含む認証ヘッダーが要求ごとに渡される必要があります。サーバーが認証キーの状態を追跡しているため、これはRESTの原則に少し違反しています。このキーの状態は維持する必要があり、ある種の有効期限の日時があり、その後はアクセスを許可しなくなります。ただし、投稿の冒頭で述べたように、アプリケーションを実際に機能させるには犠牲を払わなければなりません。とはいえ、認証トークンは、すべての可能なクライアントが有効な時間の間アクセスを許可し続けることができるような方法で保存する必要があります。あるサーバーが認証キーの状態を管理していて、別の負荷分散サーバーがそのキーに基づいて要求を満たすことができない場合、RESTの原則に本当に違反し始めました。Googleのサービスにより、携帯電話で使用していた認証トークンをいつでもロードバランスサーバーAに対して取得し、デスクトップからロードバランスサーバーBにアクセスでき、システムにアクセスでき、同じリソースにリダイレクトされます要求は同じでした。

つまり、RESTプロパティをできるだけ多く保持するために、認証トークンが何らかのバッキングストア(データベース、キャッシュなど)に対して検証されていることを確認する必要があります。

それがすべて理にかなっているといいのですが。また、チェックアウトする必要があり制約セクションのRepresentational State譲渡に関するWikipediaの記事をお持ちでない場合。RESTの信条が実際に主張していることとその理由に関しては、特に啓蒙的です。


6
最初の発言を言い換えます。RESTの制約がアプリケーションで意味をなす場合にのみ、RESTを使用してください。これらの制約のサブセットを自由に適用でき、利点のサブセットを取得できます。ただし、その時点で、独自の建築スタイルを作成しました。しかし、それは悪いことではありません。実際、ロイの論文の最初の4つの章では、原理的な設計について説明しています。RESTはほんの一例です。
Darrel Miller、

4
@ダーレルかなり十分なポイント。正直なところ、Googleがそれをどのように行うのかはわかりませんが、有効期限は認証トークンにエンコードできます。私のより大きなポイントはまだ残っていると思います。単に維持する必要のある状態のタイプがいくつかあり RESTがステートレスを要求する理由を理解している限り、システムの残りの部分に対する多くの影響やRESTfulアーキテクチャーの利点がなくても意味のある方法で違反することができます。 。
Jared Harding、

7
これまでに他の議論はなされていないので、私はこのよく書かれた応答を受け入れます。重要な部分は、ステートレスサーバーステートレスサーバーを意味しないということだと思います。誤解や誤用が多いと思います。サーバーは、べき等の動作をする限り、必要な状態を保持できます(通常は保持する必要があります)。
だます

10
私は説教をあまりにも聞いたので、セッションは落ち着きがありません。ただし、Webアプリを作成しようとしている場合、HTTP基本認証は後退の大きなステップです。
Ben Thurley 2013年

1
@Micah Henning、あなたはサーバーが認証トークンを検証するために状態情報を必要とするという誤った仮定をしています。秘密鍵がわからない場合は、公開鍵と秘密鍵のペアで署名されたトークンを偽造できないと合理的に考えることができます。トークンが有効であることを確認するには、公開鍵のみが必要です。私はまだ完全にRESTfulな認証が可能であると考えています。
jcoffland 14

12

Cookieは認証用ではありません。なぜ車輪を再発明するのですか?HTTPには、適切に設計された認証メカニズムがあります。Cookieを使用する場合、トランスポートプロトコルとしてのみHTTPを使用することになり、たとえば、ユーザーに間違った認証を提供したことをユーザーに通知するために、独自のシグナリングシステムを作成する必要があります(HTTP 401を使用すると、おそらく、Www-AuthenticateHTTP仕様に必要なクライアントへの供給:))。また、これはSet-Cookieクライアントに対する推奨事項にすぎません。Authorizationヘッダーはすべてのリクエストで自動的に送信されますが、その内容は保存される場合と保存されない場合があります(Cookieが無効になっている場合など)。

もう1つのポイントは、認証Cookieを取得するには、おそらくどこかで資格情報を最初に提供する必要があるということです。もしそうなら、それはRESTlessではないでしょうか?簡単な例:

  • GET /aクッキーなしでやってみる
  • どういうわけか認可リクエストを受け取ります
  • あなたはどういうわけか行くと承認します POST /auth
  • あなたが得る Set-Cookie
  • あなたは試すGET /a クッキー。しかしGET /a、この場合はべき等に振る舞いますか?

これを要約すると、あるリソースにアクセスして認証する必要がある場合、他の場所ではなく、同じリソースで認証する必要があると思います。


1
その間、私もこの観点にたどり着きました。技術的にはほとんど違いはないと思います。すべてが単なるHTTPヘッダーです。ただし、別のアドレスからのログインが必要な場合、認証動作自体はRESTfulではありません。したがって、Cookieは認証システムのより大きな問題の兆候にすぎません。
だます

これは、WebブラウザーがAuthorization: Basicまたはのみをサポートしているという事実を実際には説明していませんDigest。ブラウザコンテキストで基本認証またはダイジェスト認証よりも高度な処理を実行する場合(必要な場合)、Authorizationヘッダー以外のものが必要になります。
Oliver Charlesworth 2017

1
絶対に-純粋なJSを実行している場合、基本的には問題ありません(たとえば、WebSocketを除く)。しかし、私のポイントは、APIベースの認証が必ずしもブラウザーのシナリオにおける唯一の考慮事項ではないということです。
オリバーチャールズワース2017

5
GET /aCookieなしとCookieありは明らかに2つの異なる要求であり、それらが異なる動作をすることは許容されます。
TRiG

1
@TRiGへ追加するには、このロジック以下、GET /a認証ヘッダでも同様であるGET /aRESTのために、それは等しく使用できなくなって、認証ヘッダ無し。あるHTTPヘッダーを別のHTTPヘッダーとは異なる方法で処理する場合は、少なくともそれを処理する必要があります。
ジャスパー

7

実際、RESTfulnessはRESOURCESにのみ適用され、Universal Resource Identifierで示されています。したがって、RESTに関してヘッダーやCookieなどについて話すことさえ、適切ではありません。RESTは、HTTPを介して日常的に行われていますが、どのプロトコルでも機能します。

主な決定要素は次のとおりです。URIであるREST呼び出しを送信すると、呼び出しがサーバーに正常に送信されると、遷移が実行されていないと仮定して(PUT、POST、DELETE)、そのURIは同じコンテンツを返します。 ?このテストでは、エラーまたは認証リクエストが返されないようにします。その場合、リクエストはまだサーバーに届いていないため、指定されたURIに対応するドキュメントを返すサーブレットまたはアプリケーションを意味します。

同様に、POSTまたはPUTの場合、特定のURI /ペイロードを送信できます。メッセージを送信する回数に関係なく、常に同じデータを更新するため、後続のGETは一貫した結果を返しますか?

RESTはアプリケーションデータに関するものであり、データを転送するために必要な低レベルの情報に関するものではありません。

次のブログ投稿で、Roy FieldingがRESTのアイデア全体のすばらしい要約を提供しました。

http://groups.yahoo.com/neo/groups/rest-discuss/conversations/topics/5841

「RESTfulシステムは、ある定常状態から次の定常状態へと進み、そのような各定常状態は、潜在的な開始状態と潜在的な終了状態の両方です。つまり、RESTfulシステムは、単純な一連のコンポーネントに従う未知の数のコンポーネントです。常にREST状態であるか、RESTful状態から別のRESTful状態に遷移するようなルール。各状態は、その状態に含まれる表現と、それが提供する一連の遷移によって完全に理解でき、遷移は均一に制限されます。システムは複雑な状態図である場合がありますが、各ユーザーエージェントは一度に1つの状態(現在の定常状態)しか表示できないため、各状態は単純であり、個別に分析できます。ユーザー、OTOHはいつでも独自のトランジションを作成できます(例:URLの入力、ブックマークの選択、エディタなどを開きます。」


認証の問題に行くと、情報がURIとPOSTペイロードの一部でない限り、それがCookieとヘッダーのどちらを介して行われても、RESTとはまったく関係がありません。したがって、ステートレスであることに関しては、アプリケーションデータのみについて説明しています。

たとえば、ユーザーがGUI画面にデータを入力すると、クライアントは入力されたフィールド、入力されなかったフィールド、欠落している必須フィールドなどを追跡します。これはすべてクライアントコンテキストであり、送信または追跡しないでください。サーバーによって。サーバーに送信されるのは、IDENTIFIEDリソースで(URIによって)変更する必要があるフィールドの完全なセットです。これにより、そのリソースでRESTful状態から別の状態への遷移が発生します。

したがって、クライアントはユーザーが何をしているかを追跡し、論理的に完全な状態遷移のみをサーバーに送信します。


3
これがどのようにして提起された質問に光を当てているのかわかりません。
jcoffland 14

1

HTTPトランザクション、基本アクセス認証は、RBACには適していません。基本アクセス認証は、暗号化されたusername:passwordを毎回使用して識別しますが、RBACで必要なのは、ユーザーが特定の通話に使用する役割です。RBACは、ユーザー名ではなく、ロールに対する権限を検証しません。

次のようにトリックして連結することもできます:usernameRole:password。これは悪い習慣です。また、ユーザーがより多くのロールを持っている場合、認証エンジンは連結ですべてのロールをテストする必要があり、そのたびにすべての呼び出しを繰り返す必要があります。これは、RBACの最大の技術的利点の1つ、つまり非常に迅速な承認テストを破壊します。

そのため、基本的なアクセス認証を使用してその問題を解決することはできません。

この問題を解決するには、セッションを維持する必要があります。これは、一部の回答によれば、RESTと矛盾しているようです。

それが、RESTを宗教として扱うべきではないという答えについて私が気に入っている点です。複雑なビジネスケース、たとえばヘルスケアでは、RBACは絶対的に一般的で必要です。また、RESTツールの設計者はすべてRESTを宗教として扱うため、RESTの使用が許可されないのは残念です。

私にとって、HTTPを介してセッションを維持する方法は多くありません。sessionIdを持つCookie、またはsessionIdを持つヘッダーを使用できます。

誰かが別のアイデアを持っているなら、私はそれを聞いてうれしいです。



-4
  1. セッションはRESTレスではありません
  2. http専用のRESTサービスですか、それとも間違っているのですか?Cookieベースのセッションは、独自の(!)httpベースのサービスにのみ使用する必要があります!(たとえば、モバイル/コンソール/デスクトップ/などからのCookieを処理することは問題になる可能性があります。)
  3. サードパーティの開発者にRESTfulサービスを提供し、Cookieベースのセッションを使用しない場合は、代わりにトークンを使用してセキュリティの問題を回避してください。

3
認証トークンを保持するサーバー上のセッションのセッションキーを保存するためにCookieを使用しないでください。しかし、Cookieが認証トークン自体を保持している場合、それは実行可能なソリューションです。(もちろん、Cookieはhttponlyで保護されている必要があります)
roberkules 2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.