web-dev-qa-db-ja.com

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

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

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

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

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

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

私の仮定は間違っていますか?セッションCookieがRESTlessになる理由は何ですか?

451
deceze

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

  • RESTful:

    この節で説明されているREST制約に準拠しているアプリケーションは "RESTful"と見なすことができます[15]。サービスが必要な制約のいずれかに違反している場合は、RESTfulと見なすことはできません。

    によると ウィキペディア

  • ステートレス制約

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

    によると フィールディング論文

そのため、サーバー側セッションはRESTのステートレスな制約に違反し、RESTfulnessにも違反します。

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

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

私の意見では、クッキーに問題はありません。 Cookieテクノロジは、格納されたデータがすべての要求によってCookieヘッダーに自動的に添付されるクライアント側の格納メカニズムです。そのようなテクノロジに問題があるREST制約はわかりません。だから技術自体に問題はありません、問題はその使用法にあります。 Fieldingがサブセクションを書いた なぜHTTPクッキーが悪いと思うのかについて。

私の視点から:

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

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

Figure 1. - Stateless authentication by trusted clients

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

すべてのリクエストを認証しなければならないので、物事を早くするためにはおそらくサーバー側にインメモリ認証キャッシュが必要です。

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

Figure 2. - Stateless authentication by 3rd party clients

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

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

279
inf3rno

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

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

GoogleのWebサービスは、RESTfulシステムの素晴らしい例です。リクエストごとに渡されるユーザーの認証キーを含む認証ヘッダーが必要です。サーバは認証キーの状態を追跡しているので、これはRESTの原則に多少違反します。このキーの状態は維持する必要があり、それ以降はアクセス権が付与されなくなるようなある種の有効期限があります。しかし、私が私の記事の冒頭で述べたように、アプリケーションが実際に動くようにするために犠牲を払う必要があります。そうは言っても、認証トークンは、有効な期間中、すべてのクライアントが引き続きアクセスを許可できるような方法で格納する必要があります。あるサーバーが認証キーの状態を管理していて、別の負荷分散サーバーがそのキーに基づいて要求を満たすことができない場合は、RESTの原則に違反し始めています。 Googleのサービスでは、いつでも電話で使用していた認証トークンをロードバランスサーバーAに対して使用し、デスクトップからロードバランスサーバーBにアクセスしてもシステムにアクセスでき、同じリソースにアクセスできるようになります。要求は同一でした。

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

私はそれがすべて理にかなっていることを願っています。まだ行っていなければ、 Representational State Transferに関するウィキペディアの記事Constraintsセクション もチェックしてください。 RESTの教義が実際に何について論じているのか、そしてその理由については特に啓発的です。

322
Jared Harding

クッキーは認証用ではありません。なぜ車輪を作り直すのですか? HTTPはうまく設計された認証メカニズムを持っています。 Cookieを使用する場合は、トランスポートプロトコルとしてのみHTTPを使用することになります。したがって、たとえば、間違った認証を提供したことをユーザーに通知するには、ownシグナリングシステムを作成する必要があります。 HTTPの仕様で要求されているように、クライアントにWww-Authenticateを提供しない可能性があるので間違っています:))。 Set-Cookieはクライアントにとっての唯一の推奨事項です。 Authorizationヘッダーはリクエストごとに自動的に送信されますが、その内容は保存される場合も保存されない場合もあります。

もう1つのポイントは、認証Cookieを取得するには、おそらく最初にどこかに資格情報を入力したいということです。もしそうなら、それはRESTレスではないでしょうか?簡単な例:

  • クッキーなしでGET /aを試す
  • どういうわけかあなたは承認要求を受けます
  • あなたはPOST /authのようにどうにかして承認します
  • あなたはSet-Cookieを得ます
  • GET /awith cookieを試してみてください。しかし、この場合GET /aは同じように動作しますか?

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

12
starteleport

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

主な決定要因はこれです。URIであるREST呼び出しを送信した場合、呼び出しがサーバーに正常に行われると、遷移が行われなかったと仮定して、そのURIは同じ内容を返します(PUT、 POST、DELETE)この場合、エラーまたは認証要求が返されることは除外されます。その場合、要求はまだサーバーに送信されていないため、指定されたURIに対応するドキュメントを返すサーブレットまたはアプリケーションです。

同様に、POSTやPUTの場合、あなたは与えられたURI /ペイロードを送ることができます、そしてあなたがメッセージを送る回数に関係なく、それは常に同じデータを更新するでしょう。一貫した結果?

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

次のブログ記事で、Roy FieldingはRESTというアイデア全体のNice要約を出しました。

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

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


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

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

そのため、クライアントはユーザーが行っていることを追跡し、論理的に完了した状態遷移のみをサーバーに送信します。

7
Ken Kopelson

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

UsernameRole:passwordですが、これは悪い習慣です。また、ユーザーがより多くの役割を持つ場合、認証エンジンはすべての役割を連結でテストする必要があるため、すべての呼び出しを再度呼び出す必要があるため、非効率です。これはRBACの最大の技術的利点の1つ、すなわち非常に迅速な認証テストを破壊するでしょう。

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

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

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

私にとっては、HTTP経由でセッションを維持する方法はあまりありません。 sessionIdとともにcookie、またはsessionIdとともにヘッダーを使用できます。

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

1
Bert Verhees