RESTアプリケーションがステートレスであることが想定されている場合、セッションをどのように管理しますか?


536

いくつかの説明が必要です。私はRESTについて読んでいて、RESTfulアプリケーションを構築しています。ウィキペディアによれば、REST自体は、Representational State Transferとして定義されています。したがって、私は誰もが吐き続けているこの無国籍のゴブレイディーグックをすべて理解していません。

ウィキペディアから:

特定の時点で、クライアントはアプリケーションの状態間または「休止中」に移行できます。休止状態のクライアントは、ユーザーと対話できますが、サーバーのセットまたはネットワーク上で負荷を発生させず、クライアントごとのストレージを消費しません。

彼らは単にセッション/アプリケーションレベルのデータストアを使用しないと言っていますか???

RESTの1つの目標は、たとえば、ページング要求を投稿内に隠して、要求のページ番号をGET URIの一部にするのではなく、URIアクセスを一貫して利用可能にすることです。私には理にかなっています。しかし、クライアントごとのデータ(セッションデータ)をサーバー側に保存するべきではないと言っているだけのようです。

メッセージのキューがあり、ユーザーがメッセージを読みたいが、メッセージを読んでいるときに、セッション中に特定の送信者のメッセージがブロックされるようにしたい場合はどうなりますか?これをサーバー側の場所に保存し、ユーザーがブロックしていないメッセージ(またはメッセージID)のみをサーバーに送信させるのは意味がないのでしょうか。

新しいメッセージリストを要求するたびにブロックするために、メッセージ送信者のリスト全体を送信する必要がありますか?私に関係のあるメッセージリストは、そもそも公に利用できるリソースではないはずです。

繰り返しますが、これを理解しようとしています。誰かが明確にしてください


更新:

スタックオーバーフローの質問が見つかりましたが、そこまでは行きませんでした。 重要なクライアントの状態すべてのリクエストで転送する必要があるというRESTでの状態の管理方法 ... Ugg ..オーバーヘッドが多いようです...これでよろしいですか?


2
@ S.Lott:意図的に誤解を招くとは思わない。用語がわかりにくいので誤解だと思います。
私の正しい意見2010年

2
@ちょうど私の正しい意見:興味深い推測。「ステートレス」がRESTプロトコル自体がステートレスであることは明らかであるため、私自身はそのようなことを信じることができませんでした。これは、基礎となるアプリケーションの状態については何も言わず、PUT、POST、およびDELETE要求でそれを更新します。
S.Lott

@ S.Lott:HTTPプロトコル自体はステートレスです。以下で説明することから、RESTは、(DBなどの他の種類の状態とは対照的に)Webサーバーにセッション状態を処理させずにアプリを構築する方法の観点です。REST プロトコルだとは思っていませんでしたが、HTTPプロトコルの使用方法についての見解でした。私は思ったあなたたちはそれがすべてのクライアントの特定のセッションデータクライアント側の店舗を持つ、とURIは、彼らがすべきではない場合を除いて、できるだけ冪等としてアクセスすることによって、スケールにアプリケーションをビルドする方法についてだったこと、それをクリアしました。多分そうではない... :(
Zak

1
「たぶん……」どういう意味?新しい質問がありますか?SOで検索してみてください。ここに存在しない場合は、尋ねてください。
S.Lott

誰かがウェバー、パラスタチディス、ロビンソンのReSTを実際に読んだことがありますか(または、そうでなければレストバックの例を見ました)。以下の答えは理にかなっていますが、Restbucksの例のコーヒー注文は確かにクライアントについての状態ですか?注文の数はクライアントの数に比例します。クライアントの状態とリソースの境界はどこですか?
Rikki

回答:


340

ステートレスとは、すべてのHTTPリクエストが完全に分離して発生することを意味します。クライアントがHTTP要求を行うと、サーバーがその要求を満たすために必要なすべての情報が含まれます。サーバーは、以前の要求からの情報に依存することはありません。その情報が重要である場合、クライアントは後続のリクエストでそれを再度送信する必要があります。無国籍はまた、新しい機能をもたらします。ロードバランスされたサーバー間でステートレスアプリケーションを配布する方が簡単です。ステートレスアプリケーションは、キャッシュするのも簡単です。

実際には2種類の状態があります。クライアント上にあるアプリケーションの状態とサーバー上にあるリソースの状態。

Webサービスは、実際にリクエストを行っているときのみ、アプリケーションの状態を考慮する必要があります。残りの時間、それはあなたが存在することさえ知りません。つまり、クライアントがリクエストを行うときは常に、サーバーがそれを処理するために必要なすべてのアプリケーション状態を含める必要があります。

リソースの状態はすべてのクライアントで同じであり、その適切な場所はサーバー上です。画像をサーバーにアップロードすると、新しいリソースが作成されます。新しい画像には独自のURIがあり、将来のリクエストのターゲットになる可能性があります。このリソースは、HTTPを介してフェッチ、変更、削除できます。

これが無国籍とさまざまな状態の意味を区別するのに役立つことを願っています。


4
これは、リクエストが送信されるたびに、クライアントが認証のためにユーザー/パスワードを送信する必要があることを意味しますか?セッションを格納しているのは、すべてのサーバー間で共有されている非SQLデータベース上であっても、ステートレスではないためでしょうか。
Carlos NavarroAstiasarán17年

1
@CarlosNavarroAstiasaránステートレス認証を処理するためのさまざまな手法があります。たとえば、Google JWT。
ジオイデシック2018年

1
@geoidesic:「JSON Webトークンはステートレスであるため、サーバーの状態を保存せずにトークンを無効にすることはできないため、ステートレストークンの利点が失われます。」WIkipedia
ulatekh

@ulatekhこれは、トークンを使用して何ができるかについての全体的な不実表示です。承認されたIDをトークンと共に保存し、承認されたIDを持つトークンのみをクレームとして受け入れるのは非常に簡単です。ステートレスは、データベースに何かを入れられないという意味ではありません。基本的に、トークン内の同じIDと一致する必要があるIDをデータベースに格納します。トークンを取り消すには、データベースからIDを削除します。サービス自体には状態は記憶されません。または、ユーザーと一緒にデータベースに署名キーを保存し、キーを取り消します。
Andrew T Finnell

@AndrewTFinnell:承認済みIDをサーバーに保存する必要がある場合は、RESTログインを処理できる可能性のあるすべてのサーバーに保存する必要があります。これには、大規模な並列Webサーバーアーキテクチャ全体で多くのサーバー状態が含まれる可能性があります。
ulatekh

491

基本的な説明は次のとおりです。

サーバーにクライアントセッション状態はありません。

ステートレスとは、サーバーがサーバー側のクライアントセッションに関する状態を保存しないことを意味します。

クライアント・セッションは、クライアントに保存されています。サーバーはステートレスです。つまり、すべてのサーバーがいつでもどのクライアントにもサービスを提供でき、セッションアフィニティスティッキーセッションはありません。関連するセッション情報はクライアントに保存され、必要に応じてサーバーに渡されます。

これは、Webサーバーが通信する他のサービスがショッピングカートなどのビジネスオブジェクトに関する状態を維持することを妨げるものではなく、クライアントの現在のアプリケーション/セッションの状態に関するものだけではありません。

クライアントのアプリケーションの状態をサーバーに保存されていませんが、周りから渡されるんクライアント、それを必要とするすべての場所に。

これが、RESTSTの由来であるState Transferです。サーバーに保存する代わりに、状態を転送します。これは、数百万の同時ユーザーにスケールする唯一の方法です。何百万ものセッションが何百万ものセッションであること以外に理由がない場合。

セッション管理の負荷はすべてのクライアントに分散され、クライアントはセッションの状態を保存し、サーバーは数桁以上のクライアントにステートレスな方法でサービスを提供できます。

数万人の同時ユーザーでのみ必要となるサービスであっても、サービスをステートレスにする必要があります。数万はまだ数万であり、それに関連する時間とスペースのコストが発生します。

ステートレスとは、一般にHTTPプロトコルとWebがどのように動作するように設計され、全体的にシンプルな実装であり、一連のサーバー側ロジックではなく単一のコードパスを使用して、一連のセッション状態を維持します。

いくつかの非常に基本的な実装原則があります。

これらは実装ではなく原則であり、これらの原則を満たす方法は異なる場合があります。

要約すると、5つの主要な原則は次のとおりです。

  1. すべての「もの」にIDを与える
  2. 物事をリンクする
  3. 標準的な方法を使用する
  4. 複数の表現を持つリソース
  5. ステートレスに通信する

REST 論文では、認証や承認については何もありません。

RESTfulなリクエストとそうでないリクエストを認証することに違いはないからです。認証はRESTfulな議論とは無関係です。

特定の要件に合わせてステートレスアプリケーションを作成する方法を説明することは、StackOverflowにはあまりにも広範です。

RESTに関連する認証と承認の実装は非常に広範であり、実装へのさまざまなアプローチがインターネット上で非常に詳しく説明されています。

これについてのヘルプ/情報を求めるコメントは、「不要になった」というフラグが付けられるだけ です。


22
これは、何百万ものユーザーにスケーリングする唯一の方法であるというかなり大胆な声明のようです。サーバー側のセッションを単なる別のサービスにできないのはなぜですか?
Zak

27
@Zak:何百万ものセッションが何百万ものセッションだからです。ポイントは、このすべてのセッション管理のオーバーヘッドを回避することです。
S.Lott、

91
大胆さではなく、経験

21
私の回答には、すべてのリクエストでのデータベースアクセスに基づくソリューションを意味するものはありません。そうだと思っても、その規模での認証と承認を理解するのはあなたの側の失敗です。認証は状態で暗黙的である場合があります、あなたはFacebookがREST APIのすべてのリクエストで「データベースアクセス」を行うと思いますか?それともグーグル?ヒント:いいえ

6
したがって、ユーザー状態を分散キャッシュに保存する場合、memcacheを使用し、すべてのWebサーバーで状態を保存する必要はなく、状態をmemcacheから取得する場合、このアプリケーションをステートレスと見なすことができますか?
Jaskey 2014年

76

彼らは単にセッション/アプリケーションレベルのデータストアを使用しないと言っていますか???

いいえ、彼らはそれを簡単な方法で言っていません。

彼らは「セッション」を定義しないと言っている。ログインしないでください。ログアウトしないでください。リクエストに認証情報を提供します。各リクエストは独立しています。

まだデータストアがあります。あなたはまだ認証と認可を持っています。セッションの確立とセッション状態の維持に時間を無駄にしないでください。

重要なのは、各リクエストが(a)完全に独立していて、(b)実際の作業なしで、巨大な並列サーバーファームに簡単にファームできるということです。ApacheまたはSquidは、RESTfulリクエストを盲目的かつ正常に渡すことができます。

メッセージのキューがあり、ユーザーがメッセージを読みたいが、メッセージを読んでいるときに、セッション中に特定の送信者のメッセージがブロックされるようにしたい場合はどうなりますか?

ユーザーがフィルターを必要とする場合は、各要求でフィルターを提供するだけです。

それは意味がありませんか...サーバーがユーザーによってブロックされなかったメッセージ(またはメッセージID)のみを送信するようにしますか?

はい。RESTful URIリクエストにフィルターを提供します。

新しいメッセージリストを要求するたびにブロックするために、メッセージ送信者のリスト全体を送信する必要がありますか?

はい。この「ブロックするメッセージ送信者のリスト」はどのくらい大きくできますか?PKの短いリスト?

GETリクエストは非常に大きくなる可能性があります。クエリのように聞こえても、必要に応じてPOSTリクエストを試すことができます。


28
「ログインしないでください。ログアウトしないでください。リクエストに資格情報を提供してください。」私は、REST APIでステートレスを維持する方法に関する質問で、これらの資格情報をクライアントのどこにどのように保存する必要があるかについての詳細なしに、このような応答を常に見ます。確かに、ユーザー名とパスワードをローカルストレージに保存しないでください。
BeniRose 2016

2
@BeniRoseはlocalstorageにトークンを保存して、ユーザーを一意に識別するリクエストでそのトークンを使用できませんか?
Nikhil Sahu

1
Localstorageには、私が理解していることから、セキュリティに関する多くの懸念があります。しかし、また、クライアント側のセッションで他の問題の束はなど、ユーザーをログアウト、トークンを無効にするように、あります
BeniRose

3
署名のあるJWTを使用すると、署名の検証が高速になるため、その状態の有効性を確認できます。
アルキメデストラハノ2018年

36

あなたは完全に正しいです。サーバーとの完全なステートレスな相互作用をサポートすることは、クライアントに追加の負担をかけます。ただし、アプリケーションのスケーリングを検討する場合、クライアントの計算能力はクライアントの数に正比例します。したがって、多数のクライアントへのスケーリングははるかに実現可能です。

特定のクライアントの対話に関連するいくつかの情報を管理するためにサーバーに小さな責任を負うとすぐに、その負担は急速に増大してサーバーを消費する可能性があります。

それはトレードオフです。


32

ユーザーアプリケーションの状態管理の履歴ビュー

従来の意味でのセッションは、サーバー内のアプリケーションでユーザーの状態を維持します。これは、フローの現在のページであるか、以前に入力されたがまだメインデータベースに保持されていないページである可能性があります。

この必要性の理由は、クライアント固有(つまりブラウザ固有)のアプリケーションまたはプラグインを作成せずに状態を効果的に維持するためのクライアント側の標準がないことでした。

HTML5およびXMLヘッダーリクエストは、サーバー間を行き来することなく、クライアント(ブラウザ)側でアプリケーションの状態を含む複雑なデータを標準的な方法で保存するという概念を時間の経過とともに標準化しました。

RESTサービスの一般的な使用法

RESTサービスは通常、実行する必要があるトランザクションがある場合、またはデータを取得する必要がある場合に呼び出されます。

RESTサービスは、エンドユーザーから直接ではなく、クライアント側のアプリケーションから呼び出されることを意図しています。

Authenticating

サーバーへのリクエストでは、リクエストの一部に認証トークンが含まれている必要があります。実装方法はアプリケーション固有ですが、一般的には認証BASICまたはCERTIFICATE認証形式です。

フォームベースの認証はRESTサービスでは使用されません。ただし、上記のように、RESTサービスはユーザーが呼び出すのではなく、アプリケーションが呼び出すことを目的としています。アプリケーションは、認証トークンの取得を管理する必要があります。私の場合、JASPICとOAuth 2.0を組み合わせた Cookieを使用してGoogleに接続し、認証とシンプルなHTTP認証を使用して自動テストを行いました。ローカルテストにもJASPIC介したHTTPヘッダー認証も使用しました(SiteMinderでも同じアプローチを実行できます)

これらの例のように、認証はクライアント側で管理されます(SiteMinderまたはGoogleは認証セッションをクライアント側に保存します)、その状態について実行できることは何もありませんが、RESTサービスアプリケーションの一部ではありません。

取得リクエスト

RESTの取得要求はGET、特定のリソースが要求され、キャッシュ可能な操作です。リクエストにはデータを取得するために必要なすべてのものが含まれているため、サーバーセッションは必要ありません。認証とURIです。

トランザクションスクリプト

上記のように、クライアント側アプリケーション自体は、クライアント側で管理する認証とともにRESTサービスを呼び出します。

RESTサービスのこれが意味すること(正しく行われている場合)は、RESTサーバーへの単一の要求を受け取り、単一のトランザクションで必要なすべてを実行する単一のユーザー操作に必要なすべてを含むことです。トランザクションスクリプトはそのパターンです。と呼ばれます。

これはPOST通常、リクエストを通じて行われますが、などPUTも使用できます。

RESTの不自然な例の多くは(私自身はこれをしなかった)、私はもっと実用的であることを決めたとし、それを残していることを経て、HTTPプロトコルで定義されているものの多くとして従うことをしようとしただけでGETとPOST。このPOSTメソッドは、POST-REDIRECT-GETパターンを実装する必要さえありません。

それにもかかわらず、上記で述べたように、クライアント側アプリケーションはサービスを呼び出すものであり、POST必要なときに(毎回ではなく)すべてのデータを使用して要求を呼び出すだけです。これにより、サーバーへの継続的な要求が防止されます。

投票

RESTはポーリングにも使用できますが、ブラウザーの互換性のために使用する必要がない限り、お勧めしません。そのために、APIコントラクトも設計したWebSocketを使用します。古いブラウザのもう1つの代替手段は、CometDです。


27

RESTは非常に抽象的です。これは、いくつかの優れたシンプルで現実的な例を示すのに役立ちます。

たとえば、すべての主要なソーシャルメディアアプリ-Tumblr、Instagram、Facebook、Twitterを例に考えてみましょう。すべてが永久スクロールビューで、下にスクロールすればするほど、表示されるコンテンツが増え、過去にさかのぼります。ただし、スクロールした場所を失うと、アプリがあなたをトップにリセットする瞬間を経験しました。アプリを終了した場合と同様に、アプリを再び開くと、再びトップに戻ります。

理由は、サーバーがセッション状態を保存しなかったためです。残念なことに、スクロール位置はクライアントのRAMに保存されていました。

幸い、再接続時に再度ログインする必要はありませんが、これはクライアント側にも保存されているログイン証明書の有効期限が切れていないためです。アプリを削除して再インストールすると、サーバーがIPアドレスをセッションに関連付けなかったため、再度ログインする必要があります。

サーバーにはログインセッションがありません。RESTに準拠しているためです。


上記の例にはWebブラウザーはまったく含まれていませんが、バックエンドでは、アプリはHTTPSを介してホストサーバーと通信しています。私のポイントは、RESTにCookieやブラウザなどを含める必要がないということです。クライアント側のセッション状態を保存するには、さまざまな方法があります。

しかし、Webブラウザーについて少し話しましょう。これは、RESTのもう1つの主要な利点をもたらすためです。

サーバーがセッション状態を保存しようとした場合、個々のクライアントをどのように識別しますか?

多くの人が共有ルーターで同じアドレスを使用している可能性があるため、IPアドレスを使用できませんでした。では、どうやって?

さまざまなブラウザーとアプリで複数の異なるFacebookアカウントに同時にログインできるため、MACアドレスを使用することはできません。あるブラウザーは別のブラウザーになりすましやすく、MACアドレスも簡単に偽装できます。

サーバーは、ユーザーを識別するためにクライアント側の状態を保存する必要がある場合、リクエストの処理にかかる時間よりも長くRAMに保存する必要があります。そうでない場合は、そのデータをキャッシュする必要があります。サーバーのRAMとキャッシュの容量は限られていますが、プロセッサの速度は言うまでもありません。サーバー側の状態は、3つすべてに指数関数的に追加されます。さらに、サーバーがセッションに関する状態を保存する場合は、現在ログインしているブラウザとアプリごとに、また使用するデバイスごとに個別に保存する必要があります。


では、RESTがスケーラビリティにとって非常に重要である理由を今すぐ理解していただければ幸いです。サーバー側のセッション状態がサーバーのスケーラビリティーであり、溶接されたアンビルが車の加速にあるのはなぜかを理解し始めることができると思います。


人々が混乱するのは、「状態」は、データベースに格納されている情報などを指すと考えることです。いいえ、それはあなたがそれを使用しているときにサーバーのRAMにある必要があるすべての情報を指します。


13

ここでの基本的な問題は、SessionStateを混同していることです。また、RESTは状態をサーバーに保存してはならないことを指定していますが、ユーザーSessionの保存を妨げるものはありません。

サーバーで状態を管理するということは、サーバーがクライアントの動作(アプリケーションのどのセクションでどのページを表示しているか)を正確に把握しているということです。そして、これはあなたがする必要はないはずです。

セッションストレージを最小サイズに保つ必要があると他の人が同意します。それは常識ですが、実際にはアプリケーションにも依存しています。つまり、要するに、キャッシュされたデータを使用してセッションを維持し、サーバーにかかる負荷を減らしてリクエストを処理し、クライアントが使用する一時的な認証/アクセストークンを提供して認証を管理することができます。セッション/トークンが期限切れになるたびに、新しいものを生成し、クライアントにそれを使用するように依頼します。

誰かがクライアントがトークンをよりよく生成すべきだと主張するかもしれません。私はそれが両方の方法で機能すると言います、そしてそれはアプリケーションに依存し、誰がAPIを使用するかによります。

また、サーバー上に機密セッションデータを保持することは、正しい方法です。(たとえば) "isFreeGift"という名前のフィールドを含むショッピングカートをクライアントが保持することを信頼することはできません。このような情報はサーバーに保持する必要があります。

Santanu Deyが彼の回答で提供したビデオリンクは役に立ちます。まだの方はご覧ください。

余談ですが、すでに与えられたすべての回答は、一部の操作がサーバーに重い負荷を引き起こす可能性があるという事実を無視しているようです。これは、電力消費量、ハードウェア消費量、およびコスト(CPUサイクルによってレンタルされるサーバーの場合)の点で重要です。優れた開発者は、電気とメンテナンス料金を支払っていないレンタルサーバーの最新のCPUで操作を非常に迅速に実行できるとしても、アプリケーションの最適化に怠惰であってはなりません。

質問は数年前のものですが、私の答えが参考になれば幸いです。


4
私は一般的にこの意見に同意しますが、セッション識別子でさえサーバーに保存されるべきではないと主張する最近の傾向があります。私は別の解決策は、JWTはよく喧伝されているかを調べるために、まだましたが、落とし穴の一握りが付属しています:cryto.net/~joepie91/blog/2016/06/19/...
BeniRose

11

ステートレスとは、サービスの状態が後続の要求と応答の間で持続しないことを意味します。各リクエストには独自のユーザー認証情報があり、個別に認証されます。ただし、ステートフルでは、各リクエストは以前のリクエストから認識されます。すべてのステートフルリクエストはセッション指向です。つまり、各リクエストは以前のリクエストで行われた変更を認識して保持する必要があります。

バンキングアプリケーションは、ステートフルアプリケーションの例です。ユーザーが最初にログインした後、トランザクションを実行してログアウトします。ログアウト後にユーザーがトランザクションを実行しようとすると、ユーザーはトランザクションを実行できなくなります。

はい、httpプロトコルは本質的にステートレスプロトコルですが、ステートフルにするためにHTTP Cookieを使用します。つまり、デフォルトではSOAPです。しかし、それは同様にステートフルにすることができ、使用しているフレームワークに依存します。

HTTPはステートレスですが、別のセッショントラッキングメカニズムを使用することにより、Javaアプリケーションでセッションを維持できます。

はい、RESTでもSOAPでも、Webサービスでセッションを維持できます。サードパーティのライブラリを使用して実装することも、独自に実装することもできます。

http://gopaldas.org/webservices/soap/webservice-is-stateful-or-stateless-rest-soapから取得


11

スプーンはありません。

すべてのものを何度もサーバーに送信する」ようなステートレス性について考えないでください。ありえない。常に状態があります-データベース自体結局のところ一種の状態です。あなたは登録ユーザーなので、クライアント側の情報のセットはサーバー側なしでは有効になりません。技術的には、あなたは真に無国籍ではありません

ログインごとのディベートに関する一言

セッションを維持せず、毎回ログインしないとはどういう意味ですか?「毎回パスワードを送信する」という意味もありますが、それは単にばかげています。「もちろん、そうではなく、代わりにトークンを送信する」と言う人もいます -驚いたことに、PHPセッションはほぼ正確にそれを行っています。これは一種のトークンであるセッションIDを送信し、u / pwを毎回再送信せずに個人的なものに到達するのに役立ちます。また、非常に信頼性が高く、十分にテストされています。はい、便利ですが、これは欠点になる可能性があります。次の段落を参照してください。

設置面積を削減

代わりに何をすべきか、そして本当の意味は、Webサーバーのフットプリントを最小限に抑えることです。PHPのような言語を使用すると、セッションストレージにすべてを詰め込むことが非常に簡単になります。ただし、セッションには値札があります。複数のウェブサーバーがある場合、それらも負荷を共有するため、セッション情報を共有する必要があります-それらのいずれかが次のリクエストを処理する必要がある場合があります。

共有ストレージは必須です。サーバーは、少なくとも誰かがログインしているかどうかを知る必要があります。(そして、これを決定する必要があるたびにデータベースに煩わされると、あなたは実質的に破滅します。)共有ストレージは、データベースよりもはるかに高速である必要があります。これは誘惑をもたらします:わかりました、私は非常に高速なストレージを持っています。-そして、それが物事が逆に厄介になるところです。

つまり、セッションストレージを最小限に抑えますか?

繰り返しますが、それはあなたの決定です。パフォーマンス上の理由でそこにデータを保存できます(ほとんどの場合、データベースはRedisよりも低速です)、情報を重複して保存し、独自のキャッシュを実装できます-大量のゴミを保存すると、Webサーバーの負荷が大きくなることに注意してくださいそれらの上に。また、それらが重い負荷で壊れた場合(そして壊れる場合)、貴重な情報が失われます。RESTの考え方では、この場合に発生するのは、クライアントが同じ(!)リクエストを再度送信することであり、今回はそのリクエストが処理されます。

それをどうやってやるの?

ここには万能のソリューションはありません。私は無国籍のレベルを選択し、それで行くと思います。セッションは一部のユーザーに愛され、他のユーザーに嫌われるかもしれませんが、どこにも行きません。リクエストごとに、意味のある情報を送信してください。ただし、ステートレスをセッションがない、または毎回ログインしていると解釈しないでください。どういうわけかサーバーはそれがあなたであることを知っている必要があります。PHPセッションIDは1つの良い方法ですが、手動で生成されたトークンは別の方法です。

考えて決めてください。デザインの傾向を考慮しないでください。


1
「考えて決めてください。デザインの傾向を考慮しないでください。」残念ながら、今日は愚かにトレンドをフォローすることが非常に一般的になっています。時々SOを読むと、トレンドがあるからといってすべて同じ答えが得られるでしょう。
l00k

はい、多くのトピックでこれを見てきました。何が起こっているのかを理解すると、時々議論をやめます。当時、誰もがcontent-boxがborder-boxより優れていることに夢中になりました。IEに対する憎悪を示す1つの方法でした。それからブートストラップがやって来て、突然みんながボーダーボックスの信者になりました。トレンドは来るが、それから行く。gotoを使用し、テーブルを使用し、iframeを使用し、何をしているのか、そしてその理由を知ってください。トレンディストはあなたを倒そうとし、登録してあなたのサイトで支払います。世界は再び救った。
dkellner

@dkellner私はその部分を理解していませんでした:「サーバーは少なくとも誰かがログインしているかどうかを知る必要があります(そして、これを決定する必要があるたびにデータベースに迷惑をかけると、あなたは事実上破滅します。)」。PHPを使用してデータベースにセッションデータを保存するとします。とにかく、PHPセッションIDに基づいて、完全なユーザーデータやその他のものを取得するための後続の多くのDB要求があるので、ログインのためにDBにクエリを実行するのはなぜ悪いのでしょうか。つまり、どのような場合でもDBクエリは避けられません。また、PHPセッションIDを受け取っていない場合は、ユーザーが認証されていないため、クエリを実行する必要はありません。
user2923322

数千または数百万のユーザーがいる場合、キープアライブ、位置情報の更新、メッセージポーリング、または簡単なチェックインが必要なものを実行するたびに、dbに接続する贅沢はありません。これらの呼び出しは、データベースアクセスなしで(または最小限で)実装する必要があります。そのため、dbに関する概念全体を構築すると致命的となる可能性があります。繰り返しになりますが、適切に設計されたdbソリューションが機能する場合もありますが、典型的なプログラマーは、「OK、まず接続してユーザー情報を取得する」と言って何でも解決します。Baaaadの練習。
dkellner


3

ステートレスとステートフルの主な違いは、データが毎回サーバーに返されることです。ステートレスの場合、クライアントはすべての情報を提供する必要があるため、リクエストごとに多くのパラメーターを渡す必要がある場合があります。ステートフルでは、クリエットはこれらのパラメーターを1回渡し、それらはクライアントによって再度変更されるまでサーバーによって維持されます。

IMO、APIはステートレスである必要があります。これにより、非常に迅速にスケールアップできます。


2

クライアント側でクライアントセッションを管理する必要があります。これは、すべてのリクエストで認証データを送信する必要があることを意味します。また、必要ではありませんが、サーバー上にメモリ内キャッシュがあり、認証データとID、アクセス許可などのユーザー情報をペアにします。

このREST ステートレス性の制約は非常に重要です。この制約を適用しないと、すべてのクライアントセッションを維持することがアキレス腱となるため、サーバー側アプリケーションは適切にスケーリングできません。


各リクエストで認証データを送信する場合、ユーザーがすべてのリクエストで認証情報を再入力する必要がないように、どこに/どのように認証情報をクライアントに保存しますか?
アンバー

1

RESTfulサービスを開発する場合、ログインするには、ユーザーを認証する必要があります。可能なオプションは、ユーザーアクションを行うつもりであるたびにユーザー名とパスワードを送信することです。この場合、サーバーはセッションデータをまったく保存しません。

別のオプションは、サーバーでセッションIDを生成してクライアントに送信することです。これにより、クライアントはセッションIDをサーバーに送信し、それを使用して認証できます。これは、ユーザー名とパスワードを毎回送信するよりもはるかに安全です。誰かがそのデータを入手した場合、ユーザー名とパスワードが変更されるまで、ユーザーになりすますことができるためです。セッションIDさえ盗まれる可能性があり、その場合ユーザーはなりすましになるとあなたは言うかもしれません。ただし、この場合、ユーザーのなりすましは、セッションIDが有効な間のみ可能です。

ユーザー名とパスワードを変更するためにRESTful APIがユーザー名とパスワードを期待している場合、誰かがセッションIDを使用してユーザーになりすましても、ハッカーは実際のユーザーをロックアウトできません。

セッションIDは、ユーザーを識別する何かの一方向ロック(暗号化)によって生成され、セッションIDに時間を追加することで、セッションの有効期限を定義できます。

サーバーはセッションIDを保存する場合としない場合があります。もちろん、サーバーがセッションIDを格納している場合は、質問で定義された基準に違反します。ただし、セッションIDを特定のユーザーに対して検証できることを確認することだけが重要であり、セッションIDを保存する必要はありません。メール、ユーザーID、およびユーザー固有のプライベートデータ(お気に入りの色など)を一方向に暗号化する方法を想像してください。これは最初のレベルであり、暗号化された文字列にユーザー名の日付を追加して、2つを適用します。方法の暗号化。その結果、セッションIDが受信されると、2番目のレベルを復号化して、ユーザーが主張するユーザー名とセッション時間が正しいかどうかを判別できます。これが有効な場合、次に、その暗号化を再度実行し、それが文字列と一致するかどうかを確認することにより、暗号化の最初のレベルを検証できます。そのためにセッションデータを保存する必要はありません。


これは理にかなっている
1

0

全体の概念は異なります... RESTFulプロトコルを実装しようとしている場合は、セッションを管理する必要はありません。その場合は、すべてのリクエストで認証手順を実行することをお勧めします(パフォーマンスの点で追加のコストがかかりますが、パスワードのハッシュは良い例です。大したことではありません...)。セッションを使用する場合-複数のサーバーに負荷をどのように分散できますか?RESTFulプロトコルはセッションを完全に排除することを意図しているに違いありません-あなたは本当にそれらを必要としません...それが「ステートレス」と呼ばれている理由です。セッションが必要なのは、要求が行われた後、クライアント側にCookie以外のものを保存できない場合のみです(例として、JavaScriptやHTML5をサポートしていない古いブラウザーを例に挙げます)。「フル機能」のRESTFulクライアントの場合、通常は保存しても安全ですbase64(login:password) アプリケーションがまだロードされるまでクライアント側(メモリ内)で-アプリケーションは唯一のホストへのアクセスに使用され、Cookieはサードパーティのスクリプトによって危険にさらされることはありません...

RESTFulサービスのCookie認証を無効にすることをお勧めします...基本認証/ダイジェスト認証を確認してください-RESTFulベースのサービスにはこれで十分です。


3
クライアント側でa client side (in memory) 保存するのは何ですか?どのように安全base64(login:password)ですか?
RNクシュワハ2015

1
「完全に安全」と定義されているものはありません。ただし、APIリクエスト(基本認証)のbase64文字列を保存するよりも優れたセキュリティを提供するOAuth2を使用することを検討できます。基本認証に固執する場合は、セキュリティを強化するためにHTTPSを使用できます。
felixwcf 2016年

3
RNクシュワハ、これは、サーバーへのセッションの保存を停止してクライアントに保存するように指示されたときに誰も答えたくない質問です。
BeniRose

0

RESTはステートレスであり、リクエスト間の状態を維持しません。認証のようなユーザーの状態を維持するために、クライアントのCookie /ヘッダーが設定されます。クライアントのユーザー名/パスワードは、第3部の認証メカニズムによって検証されます。第2レベルのOTP生成など。ユーザーが認証されると、ヘッダー/ Cookieがサービスエンドポイントを公開し、ユーザーは有効なヘッダー/ Cookieを持っているので、認証としてユーザーを想定できます。 。これで、IPなどのユーザーの特定の情報がキャッシュに保持され、その後、要求がリストされたリソースの同じIP(MACアドレス)からのものである場合、ユーザーは許可されます。また、キャッシュは特定の時間維持され、時間が経過すると無効になります。したがって、キャッシュを使用するか、DBエントリを使用して、要求の情報を永続化できます。


0

ここでステートレスとは、リクエストの状態またはメタデータがサーバー側で維持されないことを意味します。サーバー上で各リクエストまたはユーザーの状態を維持することにより、パフォーマンスのボトルネックにつながります。サーバーは、特定の操作を実行するために必要な属性で要求されます。

セッションを管理したり、ユーザーにカスタマイズエクスペリエンスを提供したりするには、ユーザーの好み、過去のリクエスト履歴などのメタデータや状態を維持する必要があります。これは、Cookie、隠し属性、またはセッションオブジェクトに保持することで実行できます。

これにより、アプリケーション内のユーザーの状態を維持または追跡できます。

お役に立てれば!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.