RESTful認証


745

RESTful認証とは何を意味し、どのように機能しますか?Googleで適切な概要を見つけることができません。私の唯一の理解は、URLでセッションキー(メモ)を渡すことですが、これはひどく間違っている可能性があります。


3
Restful Authenticationをググると、ダースにRoRプラグインが見つかりました。私はそれらがあなたが探しているものではないと仮定しています。RoRでない場合、どの言語ですか?どのWebサーバー?
S.Lott、2008年

2
HTTPSを使用する場合、それはひどく間違っていることはありません。URLとともに完全なHTTPリクエストは暗号化されます。
Bharat Khatri 2013

4
@BharatKhatri:はい、そうです。ユーザーに表示されるURLで機密情報を渡すことはありません。この情報は、実際の目的で漏洩する可能性がはるかに高くなります。HTTPSは、偶発的な漏出には役立ちません。
Jo So

2
@jcoffland:実際のRESTful認証とはどういう意味ですか?受け入れられた回答から3番目の方法を実装したばかりなので、興味がありますが、それでは満足できません(URLの追加のパラメーターが好きではありません)。
BlueLettuce16 2014年

4
一部の人々はこれを解決するためにjwt.io/introductionを使用します。私は今、私のケースを解決するためにこれについて研究しています:stackoverflow.com/questions/36974163/… >>うまくいけば、これはうまく機能します。
2016年

回答:


586

RESTfulクライアント/サーバーアーキテクチャで認証を処理する方法は、議論の余地があります。

一般的に、SOA over HTTPの世界では、次の方法で実現できます。

  • HTTPS経由のHTTP基本認証。
  • クッキーとセッション管理。
  • HTTPヘッダーのトークン(例:OAuth 2.0 + JWT);
  • 追加の署名パラメーターを使用して認証を照会します。

ソフトウェアアーキテクチャを最大限に一致させるには、これらの手法を適応させるか、さらにうまく組み合わせる必要があります。

各認証スキームには、セキュリティポリシーとソフトウェアアーキテクチャの目的に応じて、独自のPROとCONがあります。

HTTPS経由のHTTP基本認証

標準のHTTPSプロトコルに基づくこの最初のソリューションは、ほとんどのWebサービスで使用されています。

GET /spec.html HTTP/1.1
Host: www.example.org
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

実装は簡単で、すべてのブラウザでデフォルトで使用できますが、ブラウザに表示されるひどい認証ウィンドウが存続する(ここではLogOutのような機能はありません)、サーバー側の追加のCPU消費など、いくつかの既知の欠点があります。ユーザー名とパスワードが(HTTPS経由で)サーバーに送信されるという事実(キーボード入力時にクライアント側にのみパスワードを保持し、サーバーに安全なハッシュとして保存する方が安全です) 。

ダイジェスト認証を使用する場合もありますが、MiM攻撃またはリプレイ攻撃に対して脆弱であり、HTTPに固有であるため、HTTPSも必要です。

Cookie経由のセッション

正直なところ、サーバー上で管理されるセッションは、本当にステートレスではありません。

1つの可能性として、Cookieコンテンツ内のすべてのデータを維持することが考えられます。そして、設計上、Cookieはサーバー側で処理されます(実際、クライアントはこのCookieデータを解釈しようとさえしません。それは、連続する要求ごとにサーバーにそれを渡すだけです)。ただし、このCookieデータはアプリケーションの状態データであるため、クライアントはサーバーではなく、純粋なステートレスの世界で管理する必要があります。

GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: theme=light; sessionToken=abc123

Cookie技術自体はHTTPにリンクされているため、プロトコルに依存しないIMHOであるRESTfulなものではありません。MiMまたはリプレイ攻撃に対して脆弱です。

トークン経由で付与(OAuth2)

別の方法として、HTTPヘッダー内にトークンを配置して、リクエストが認証されるようにすることもできます。これは、たとえばOAuth 2.0 が行うことです。RFC 6749を参照してください。

 GET /resource/1 HTTP/1.1
 Host: example.com
 Authorization: Bearer mF_9.B5f-4.1JqM

つまり、これはCookieと非常によく似ており、同じ問題が発生します。ステートレスではなく、HTTP送信の詳細に依存し、MiMやReplayなどの多くのセキュリティ上の弱点があるため、HTTPSでのみ使用されます。通常、JWTはトークンとして使用されます。

クエリ認証

クエリ認証は、URIのいくつかの追加パラメーターを介して各RESTful要求に署名することで構成されます。参照この参照記事を

それはこの記事でそのように定義されました:

すべてのRESTクエリは、プライベートクレデンシャルを署名トークンとして使用して、小文字のアルファベット順にソートされたクエリパラメータに署名することによって認証される必要があります。署名は、クエリ文字列をURLエンコードする前に行う必要があります。

この手法は、おそらくステートレスアーキテクチャとの互換性が高く、簡単なセッション管理(DB永続性の代わりにメモリ内セッションを使用)でも実装できます。

たとえば、上記のリンクからの一般的なURIサンプルは次のとおりです。

GET /object?apiKey=Qwerty2010

そのように送信する必要があります:

GET /object?timestamp=1261496500&apiKey=Qwerty2010&signature=abcdef0123456789

署名される文字列はで/object?apikey=Qwerty2010&timestamp=1261496500あり、署名は、APIキーのプライベートコンポーネントを使用したその文字列のSHA256ハッシュです。

サーバー側のデータキャッシングは常に使用できます。たとえば、フレームワークでは、URIレベルではなくSQLレベルで応答をキャッシュします。したがって、この追加のパラメーターを追加しても、キャッシュメカニズムは壊れません。

JSONとRESTに基づく、クライアントサーバーORM / SOA / MVCフレームワークでのRESTful認証の詳細については、この記事を参照してください。HTTP / 1.1だけでなく、名前付きパイプまたはGDIメッセージ(ローカル)を介した通信も許可するため、HTTP固有性(ヘッダーやCookieなど)に依存せずに、真にRESTfulな認証パターンを実装しようとしました。

後で注:URIに署名を追加することは悪い習慣と見なされる可能性があるため(たとえば、httpサーバーのログに表示されるため)、リプレイを回避するために適切なTTLなどで軽減する必要があります。しかし、httpログが危険にさらされている場合は、より大きなセキュリティ問題が確実に発生します。

実際には、OAuth 2.0向けの今後のMACトークン認証は、「Granted by Token」の現在のスキームに関して大幅な改善になる可能性があります。しかし、これはまだ進行中の作業であり、HTTP送信に関連付けられています。

結論

RESTは、実際にはほとんどがHTTPを介して実装されている場合でも、HTTPベースだけではないという結論に値します。RESTは他の通信レイヤーを使用できます。したがって、RESTful認証は、Googleが回答するものを問わず、HTTP認証の同義語ではありません。HTTPメカニズムをまったく使用しないでください。ただし、通信層から抽象化する必要があります。そして、HTTP通信を使用する場合、Let's Encryptイニシアチブのおかげで、認証スキームに加えて必要な適切なHTTPSを使用しない理由はありません。


5
Cookieより優れた代替として使用する場合はHTTP Basic Auth、認証を期限切れにする方法とログアウト機能を使用して、本当にステートレスな認証を行うことができます。実装例ではEmulated-HTTP-Basic-Auth、実際のHTTP基本認証と同様の値で呼び出されるCookieを使用し、さらに有効期限を設定できます。ログアウトは、そのCookieを削除して実装できます。HTTP Basic Authをサポートできるクライアントであれば、この方法で行われるCookie認証もサポートできると思います。
Mikko Rantalainen 2013

4
@MikkoRantalainenしかし、私が書いたように、このCookieは引き続きサーバーによって管理されます。ある種のステートレスですが、「純粋な」ステートレスではありません。いずれの場合も、クライアントのログイン/ログアウト専用のJavaScriptコードが必要です。これは、たとえばHTTPダイジェスト認証などで完全に可能です。ここでは、ホイールを再発明するための大きなメリットはありません。
Arnaud Bouchez 2013年

4
サーバーはヘッダーを構成するためのUIとロジックを実装していると主張しますが、ヘッダー自体はステートレスです。API用に設計されたクライアントは、ヘッダーを構成するためのサーバーヘルプの使用をスキップし、HTTP基本認証と同様に必要な情報を渡すだけで済みます。私のポイントは、一般的なUA(ブラウザ)のBasic Authの実装が非常に貧弱で、使用できないことです。Cookie代わりに、別のヘッダー()内の同じものに対してエミュレーションを提供するサーバーを使用できます。
ミッコランタライネン2013年


7
HTTP認証の醜いパスワードプロンプトは、サーバーが401 Unauthorized応答を送り返すことによって要求した場合にのみ表示されます。気に入らない場合は、代わりに403 Forbiddenを送信してください。エラーページには、ログインするためのメソッドまたはそれへのリンクが含まれる場合があります。ただし、Cookieとhttp認証に対する最大の議論は(状態がサーバー側かクライアント側かに関係なく)、クロスサイトリクエストフォージェリに対して脆弱であることです。このため、最善のアプローチは、カスタム認証スキーム、カスタム認証ヘッダー、またはカスタムGETまたはPOSTパラメーターです。
Dobes Vandermeer 2014年

418

「HTTP認証」と熱狂的に叫んでいる人々が、RESTを使用して(マシンツーマシンのWebサービスではなく)ブラウザベースのアプリケーションを作成しようとしたことがあるかどうかは疑問です(問題はありません。 。

ブラウザで表示するHTMLページを生成するRESTfulサービスでHTTP認証を使用するときに私が見つけた問題は次のとおりです。

  • ユーザーは通常、醜いブラウザ製のログインボックスを取得しますが、これは非常にユーザーフレンドリーではありません。パスワードの取得、ヘルプボックスなどを追加することはできません。
  • ログアウトまたは別の名前でのログインは問題です-ブラウザはウィンドウを閉じるまで認証情報をサイトに送信し続けます
  • タイムアウトが難しい

これらのポイントごとに取り組む非常に洞察に富んだ記事がここにありますが、これにより、ブラウザ固有の多くのJavaScriptハッキング、回避策の回避策などが発生します。そのため、これは前方互換性もないため、新しいブラウザがリリースされるたびに定期的なメンテナンスが必要になります。私はそのすっきりとしたデザインを考慮していません。さらに、RESTバッジを友達に熱心に見せるために、余計な手間と頭痛がたくさんあると感じています。

クッキーが解決策だと思います。しかし、待ってください、クッキーは悪ですよね?いいえ、そうではありません。Cookieがよく使用される方法は悪です。Cookie自体は、ブラウザが閲覧中に追跡するHTTP認証情報と同様に、クライアント側の情報の一部です。また、このクライアント側の情報は、HTTP認証情報と同様に、リクエストごとにサーバーに送信されます。概念的には、唯一の違いは、このクライアント側の状態の内容は、サーバーがその応答の一部として決定できることです。

以下のルールのみを使用して、セッションをRESTfulリソースにします。

  • セッションは、ユーザID(そしておそらくタイムアウトのための最後のアクション・タイムスタンプ)にキーをマップします
  • セッションが存在する場合、それはキーが有効であることを意味します。
  • ログインは/ sessionsへのPOSTを意味し、新しいキーがcookieとして設定されます
  • ログアウトとは、/ sessions / {key}を削除することを意味します(POSTがオーバーロードされているため、私たちはブラウザーであり、HTML 5はまだ長い道のりです)
  • 認証は、リクエストごとにキーをCookieとして送信し、セッションが存在して有効かどうかを確認することで行われます

HTTP認証との唯一の違いは、認証キーがサーバーによって生成され、クライアントに送信されることです。クライアントは、入力された資格情報からそれを計算するのではなく、それを送り返します。

converter42は、httpsを使用する場合(必要です)、認証情報が非セキュア接続を介して送信されないように、Cookieにセキュアフラグを設定することが重要であることを追加しています。素晴らしい点、私自身はそれを見ていない。

これは十分に機能する十分なソリューションだと思いますが、私はこのスキームの潜在的な穴を特定するのに十分なセキュリティの専門家ではないことを認めなければなりません。ログインプロトコル(PHPでは$ _SESSION、Java EEではHttpSessionなど)。cookieヘッダーのコンテンツは、accept-languageを使用して翻訳リソースなどにアクセスするのと同じように、サーバー側のリソースをアドレス指定するために使用されます。同じだと思いますが、他の人は違うのでは?皆さんどう思いますか?


68
これは実用的な答えであり、提案されたソリューションは機能します。ただし、同じ文で「RESTful」と「セッション」という用語を使用するのは間違っています(間に「not」もない限り、;)。つまり、セッションを使用するすべてのWebサービスはRESTfulではありません(定義上)。誤解しないでください。このソリューション(YMMV)は引き続き使用できますが、「RESTful」という用語は使用できません。私はRESTに関するO'Reillyの本をお勧めします。これは非常に読みやすく、主題を詳細に説明しています。
johndodo '29

23
@skrebbel:純粋なRESTソリューションは、リソースを要求するたびに認証データを送信しますが、これは完全ではありません(HTTP Authはこれを行います)。提案されたソリューションは機能し、ほとんどのユースケースに適していますが、RESTfulではありません。戦争の必要はありません、私もこの解決策を使います。それがRESTfulであるとは私は主張しません。:)
johndodo

94
さあ、例を挙げましょう。他の方法は何ですか、うまくいきますか?本当に知りたいです。HTTP Authは確かにそうではありません。ブラウザを閉じずにログアウトすることはできません。また、多くのブラウザ固有の非互換のJSがなければ、適切なログインUXを提供できません。「純粋にRESTful」か「ほぼRESTful」か、それに関連する全体的な宗教論争についてはあまり気にしませんが、いくつかの方法がある場合は、それらを詳しく説明する必要があります。
skrebbel 2011

15
実際のユーザーエージェント(別名「ブラウザ」)を使用した真のRESTful認証は、HTTP認証の値を含むCookieで構成されます。このようにして、サーバーはログインとパスワードを入力するためのUIを提供でき、サーバーは(Cookieを削除することによって)ログアウトを強制できます。さらに、サーバーは、認証が失敗したときにログインを要求するために401で応答する代わりに、ログイン画面への一時的なリダイレクトを使用し、ログインが成功した後、一時的なリダイレクトを使用して以前の場所に戻る必要があります。さらに、サーバーは、ログインしたユーザーのほぼすべてのページにログアウトアクション(POSTフォーム)を埋め込む必要があります。
ミッコランタライネン

15
セッションがクライアント側にのみ存在することが明らかである限り、同じ文で "restful"と "session"を使用しても問題はありません。なぜこのコンセプトがそんなに重要なのかはよくわかりません。
Joe Phillips

140

このトピックに関しては、すでに十分な知識がここにいる人々によって十分に述べられています。しかし、これは私の2セントです。

相互作用には2つのモードがあります。

  1. 人と機械(HTM)
  2. マシンツーマシン(MTM)

マシンは一般的な分母であり、REST APIとして表現され、アクター/クライアントは人間またはマシンのいずれかです。

さて、真にRESTfulなアーキテクチャでは、ステートレスの概念は、関連するすべてのアプリケーション状態(クライアント側の状態を意味する)がすべてのリクエストで提供される必要があることを意味します。関連するとは、REST APIが要求を処理し、適切な応答を提供するために必要なものを意味します。

Human-to-Machineアプリケーションのコンテキストでこれを考慮すると、Skrebbelが上記で指摘したように「ブラウザーベース」です。これは、ブラウザーで実行されている(Web)アプリケーションが、各リクエストでその状態と関連情報を送信する必要があることを意味しますバックエンドのREST APIになります。

これを検討してください。RESTAPIのデータ/情報プラットフォーム公開アセットがあります。おそらく、すべてのデータキューブを処理するセルフサービスのBIプラットフォームがあるでしょう。しかし、(人間の)顧客が(1)Webアプリ、(2)モバイルアプリ、(3)いくつかのサードパーティアプリケーションを介してこれにアクセスすることを望みます。結局、MTMのチェーンでさえHTMにつながります-そうです。したがって、人間のユーザーは情報チェーンの頂点にとどまっています。

最初の2つのケースでは、人間と機械の相互作用のケースがあり、情報は実際に人間のユーザーによって消費されます。最後のケースでは、REST APIを使用するマシンプログラムがあります。

認証の概念は全面的に適用されます。REST APIが統一された安全な方法でアクセスされるように、これをどのように設計しますか?これを見る方法には、2つの方法があります。

方法1:

  1. そもそもログインはありません。すべてのリクエストがログインを実行します
  2. クライアントは、その識別パラメーター+要求固有のパラメーターを各要求と共に送信します
  3. REST APIはそれらを受け取り、向きを変え、ユーザーストア(何であれ)にpingを送信し、認証を確認します。
  4. 認証が確立された場合、要求を処理します。それ以外の場合は、適切なHTTPステータスコードで拒否
  5. カタログ内のすべてのREST APIですべてのリクエストに対して上記を繰り返します

方法-2:

  1. クライアントは認証リクエストで始まります
  2. ログインREST APIは、このようなリクエストをすべて処理します
  3. 認証パラメーター(APIキー、uid / pwdまたはユーザーが選択したもの)を受け取り、ユーザーストア(LDAP、AD、またはMySQL DBなど)に対して認証を検証します。
  4. 検証された場合、認証トークンを作成し、それをクライアント/呼び出し元に渡します
  5. 呼び出し元は、この認証トークン+リクエスト固有のパラメーターを、ログアウトするまで、またはリースが期限切れになるまで、他のビジネスREST APIへの後続のすべてのリクエストとともに送信します

明らかに、Way-2では、REST APIがトークンを有効であると認識して信頼する方法が必要になります。ログインAPIが認証検証を実行したため、その「バレットキー」はカタログ内の他のREST APIによって信頼される必要があります。

もちろん、これは認証キー/トークンを保存してREST API間で共有する必要があることを意味します。この共有の信頼できるトークンリポジトリは、ローカルまたはフェデレーションにすることができ、他の組織のREST APIが相互に信頼できるようにします。

しかし、私は余談です。

重要なのは、すべてのREST APIが信頼の輪を作成できるように、「状態」(クライアントの認証済みステータスについて)を維持および共有する必要があるということです。これを行わない場合、つまりWay-1は、入ってくるすべての要求に対して認証動作を実行する必要があることを受け入れる必要があります。

認証の実行は、リソースを大量に消費するプロセスです。すべての受信リクエストに対して、ユーザーストアに対してSQLクエリを実行して、uid / pwdの一致を確認するとします。または、ハッシュ照合を暗号化して実行する(AWSスタイル)。そして、アーキテクチャ上、すべてのREST APIは、共通のバックエンドログインサービスを使用してこれを実行する必要があると思います。なぜなら、そうしないと、認証コードがどこにでも散らかされるからです。大きな混乱。

より多くの層、より多くの待ち時間。

次に、Way-1を使用してHTMに適用します。すべてのリクエストでuid / pwd / hashなどを送信する必要があるかどうか、(人間の)ユーザーは本当に気にしていますか?いいえ、毎秒auth / loginページをスローすることによって彼女を気にしない限り。あなたがそうするならば、顧客を持っている幸運。したがって、あなたがすることは、ログイン情報をクライアント側のどこかに、ブラウザの最初に保存し、すべてのリクエストに対して送信することです。(人間の)ユーザーの場合、彼女はすでにログインしており、「セッション」を利用できます。しかし、実際には、彼女はすべてのリクエストで認証されます。

Way-2と同じです。あなたの(人間の)ユーザーは気付かないでしょう。したがって、害はありませんでした。

Way-1をMTMに適用するとどうなりますか?この場合、マシンなので、すべてのリクエストで認証情報を送信するように要求することで、この人にひどい思いをさせることができます。誰も気にしない!MTMでWay-2を実行しても、特別な反応はありません。そのいまいましいマシン。気になりませんでした!

だから本当に、問題はあなたのニーズに何が合っているかです。無国籍には代償があります。代金を支払い、次に進みます。あなたが純粋主義者になりたいのなら、それもその代価を払って先に進んでください。

結局、哲学は重要ではありません。本当に重要なのは、情報の発見、提示、消費体験です。人々があなたのAPIを愛しているなら、あなたはあなたの仕事をしました。


3
先生、あなたはこれをとても美しく説明してくれたので、私は手元にある基本的な問題/質問について明確な考えを持っています。あなたは仏様です!トランスポート層でHTTPSを使用することでそれを追加できますが、Man In the Middle攻撃を防ぐこともできるため、誰も私の識別子キーをハイジャックできません(Way-1が選択されている場合)
Vishnoo Rath 14

常に認証を行うマシンではないですか?人間はパスワードについてがらくたを出しません。それは、セキュリティを正しく合理化するユーザーにとって不幸な不快感です。私にとって、マシンにどのように機能させるかは開発者の問題です。
Todd Baur、2014

9
私はあなたの答えを読みました。ソリューションでは、ユーザーのクリックによってブラウザーで発生するすべてのWebリクエストについて、ユーザーがクリックするAPIに「認証トークン」を送信する必要があります。それで?APIはトークンのチェックを実行します。何に対して?そのトークンが有効であるかどうかを維持するある種の「トークンストア」に対して。その「トークンストア」が「国家」の番人になることに同意しませんか?実際には、これをどのように見ても、誰かがユーザーアクティビティで渡される「トークン」について何かを知っている必要があります。それは州情報が住んでいるところです。
Kingz 2014

5
そして、「ステートレス」サービスによって本当に意味されるのは、その特定のサーバーコンポーネント(CRUD API)が状態を運ばないということです。彼らは、あるユーザーを別のユーザーから認識せず、1つのトランザクションでユーザー要求全体を完了します。それが無国籍です。しかし、どこかで誰かが座って、このユーザーが有効かどうかの判断を下さなければなりません。これを行う他の方法はありません。キーやパスワードなど。ユーザー側から渡されるものはすべて、認証および承認される必要があります。
Kingz 2014

1
Way-3ハイブリッドアプローチが欠けています。クライアントはと同様にログインしますWay-2が、と同様にWay-1、資格情報はサーバー側の状態に対してチェックされません。いずれにしても、のように認証トークンが作成され、クライアントに送り返されますWay-2。このトークンは、クライアント固有の状態を調べることなく、非対称暗号を使用して信頼性が後でチェックされます。
jcoffland 2015年

50

これが、真に完全にRESTfulな認証ソリューションです。

  1. 認証サーバーで公開鍵と秘密鍵のペアを作成します。
  2. 公開鍵をすべてのサーバーに配布します。
  3. クライアントが認証するとき:

    3.1。以下を含むトークンを発行します。

    • 有効期限
    • ユーザー名(オプション)
    • ユーザーIP(オプション)
    • パスワードのハッシュ(オプション)

    3.2。秘密鍵でトークンを暗号化します。

    3.3。暗号化されたトークンをユーザーに送り返します。

  4. ユーザーがAPIにアクセスするときは、認証トークンも渡す必要があります。

  5. サーバーは、認証サーバーの公開鍵を使用してトークンを復号化することにより、トークンが有効であることを確認できます。

これは、ステートレス/ RESTful認証です。

パスワードハッシュが含まれている場合、ユーザーは認証トークンとともに暗号化されていないパスワードも送信することに注意してください。サーバーは、ハッシュを比較することにより、パスワードが認証トークンの作成に使用されたパスワードと一致したことを確認できます。HTTPSなどを使用した安全な接続が必要になります。クライアント側のJavascriptは、ユーザーのパスワードを取得し、それをクライアント側にメモリまたはCookieに格納し、サーバーの公開鍵で暗号化することもできます。


5
誰かがその認証トークンを手に入れ、クライアントを装ったAPIを呼び出すとどうなりますか?
アビディ2013年

2
@アビディ、はい、それは問題です。パスワードが必要な場合があります。パスワードのハッシュを認証トークンに含めることができます。誰かがトークンを盗むことができれば、オフラインのブルートフォース攻撃に対して脆弱になります。強力なパスフレーズが選択された場合、それは問題にはなりません。httpsトークンの盗用を使用した場合、攻撃者は最初にクライアントのマシンにアクセスする必要があることに注意してください。
jcoffland

1
認証サーバーだけが秘密鍵を知っているからです。他のサーバーは、公開鍵とユーザーのトークンを知っているだけでユーザーを認証できます。
jcoffland 2014

1
非対称暗号化と復号化は、対称暗号化よりも桁違いに遅く(計算集約的)です。サーバーが公開鍵を使用してすべての呼び出しでトークンを復号化すると、パフォーマンスが非常にボトルネックになります。
Craig

3
@jcofflandあなたは本当にここであなたの答えを宣伝しました(繰り返し:-)しかし、すべての呼び出しで非対称暗号化を使用することのパフォーマンス問題(計算強度)についてコメントすることはできません。私はそれを行うソリューションがスケーリングする能力を持っているのを見ることができません。HTTPSとSPDYプロトコルを調べます。接続を開いたままにし(状態を維持するHTTPキープアライブ)、同じ接続(複数の状態)で複数のリソースをバッチで提供するために必要な時間を確保します。もちろん、SSL自体は非対称暗号化のみを使用して対称暗号鍵を交換します(状態も)。
Craig

37

正直なところ、私はここで素晴らしい答えを見てきましたが、少し気になるのは、誰かがステートレスの概念全体を極端にして、それが独断的になるときです。それは、純粋なOOだけを採用したいと思っていた古いSmalltalkファンを思い出させます。何かがオブジェクトでない場合、それは間違っています。休憩してください。

RESTfulなアプローチは、あなたの人生をより簡単にし、オーバーヘッドとセッションのコストを削減することになっています、それは賢明なことなので、それに従ってください、しかしあなたがその分野(極端な分野/ガイドライン)を極限までフォローすることそれが意図されていた利点をもはや提供しない場合、あなたはそれを間違っています。今日の最高の言語のいくつかは、関数型プログラミングとオブジェクト指向の両方を備えています。

問題を解決する最も簡単な方法が、認証キーをCookieに保存してHTTPヘッダーで送信することである場合は、それを実行してください。悪用しないでください。セッションが重くて大きくなるとセッションが悪くなることに注意してください。すべてのセッションがキーを含む短い文字列で構成されている場合、何が問題なのでしょうか。

私はコメントの修正を受け入れる用意がありますが、サーバーにハッシュの大きな辞書を保持することを単に回避するために私たちの生活を悲惨なものにすることのポイント(今のところ)がわかりません。


2
人々はあなたがセッションを使用することを禁止しようとはしていません。あなたはそれを自由に行うことができます。しかし、そうした場合、それはRESTではありません。
アンドレ・カルダス

6
@AndréCaldasこれは、言語に関数やプリミティブ型を持たせることがうまくいかないのと同じようにRESTではありません。私はセッションをすることが賢明だと言っているのではありません。私は彼らがもはや誰かに利益をもたらさない程度まで一連の実践に従うことについて私の意見を述べています。(ところで、私はあなたの発言に反対しなかったことに注意してください、しかし、それがRESTでないとは言いません、それは純粋な RESTではないと思います)。
arg20

それがRESTfulでない場合、それを何と呼びますか?そして確かに、リクエストにセッションIDが含まれている場合、それはユーザーIDを含むリクエストと同じくらいステートレスです。ユーザーIDがステートレスで、セッションIDがステートフルなのはなぜですか?
mfhholmes 2013

1
Cookieはクロスサイトリクエストフォージェリに対して脆弱であるため、セキュリティ侵害が発生しやすくなります。カスタムヘッダーやカスタム認証スキームなど、ブラウザによって自動的に送信されないものを使用することをお勧めします。
Dobes Vandermeer 2014年

1
実際、ステートレスになることは独断主義ではなく、SOA自体の1つの一般的な概念についてです。サービスは常に、分離されたステートレスであることから利益を得る必要があります。実際には、スケーリング、可用性、保守性が容易になります。もちろん、それは可能な限り多くする必要があり、最終的には、これらのステートレスなサービスをステートフルな実用的なアプローチに管理するための「オーケストレーションサービス」が必要になります。
Arnaud Bouchez

32

よりもまず、RESTful WebサービスはSTATELESS(つまり、SESSIONLESS)です。)。したがって、RESTfulサービスには、セッションまたはCookieの概念が含まれていないはずです。RESTfulサービスで認証または許可を行う方法は、RFC 2616 HTTP仕様で定義されているHTTP Authorizationヘッダーを使用することです。すべてのリクエストにはHTTP Authorizationヘッダーが含まれている必要があり、リクエストはHTTP(SSL)接続を介して送信される必要があります。これは、HTTP RESTful Webサービスで認証を行い、リクエストの承認を確認する正しい方法です。Cisco SystemsでCisco PRIME Performance Managerアプリケーション用のRESTful Webサービスを実装しました。そして、そのWebサービスの一部として、認証/承認も実装しました。


5
HTTP認証でも、サーバーはユーザーIDとパスワードを追跡する必要があります。これは完全に無国籍ではありません。
jcoffland 14

21
各要求は、以前の要求の要件なしでそれ自体で有効であるという意味でステートレスです。これがサーバーに実装される方法は別の問題です。認証にコストがかかる場合は、キャッシュを実行して、キャッシュミス時に再認証することができます。出力が純粋に入力の関数である完全にステートレスなサーバーはほとんどありません。これは通常、ある状態のクエリまたは更新です。
エリックマルティーノ

3
違います。この場合、すべての要求には、前のトランザクション、つまりユーザー登録の状態が必要です。サーバーに保存されているユーザー名とパスワードはサーバー側の状態ではないと人々が言い続けようとする理由がわかりません。私の答えを見てください。
jcoffland 14

1
@jcofflandまた、ソリューションは、署名済みトークンを復号化するAPIサーバーの機能に大きく依存しています。このアプローチは具体的すぎるだけでなく、R。フィールディングがRESTful認証の問題に取り組むことを念頭に置いたRフィールディングが考えたには少し洗練されすぎていると思います。
Michael Ekoka 2014

2
@jcofflandは、計算集約型(したがって、リソース集約型であり、処理速度が非常に遅い)の非対称暗号化がどれほど深刻であるかを理解していますか?あなたは、すべてのリクエストで非対称暗号化を使用するスキームについて話しています。HTTPSの最も遅い側面は、何もないことですが、その後のすべての通信を対称的に暗号化するために後で使用される共有シークレットを非対称的に暗号化する公開鍵/秘密鍵の作成を含む最初のハンドシェイクです。
Craig

22

RESTのすべての制約内で実行されるセッションレス認証を指すために一般的に使用されるため、これは「セッションキー」に関するものではありません。各要求は自己記述型であり、サーバー側のアプリケーションの状態なしで、要求を承認するのに十分な情報を伝達します。

これに取り組む最も簡単な方法は、RFC 2617の HTTPの組み込み認証メカニズムから始めることです。


HTTP認証では、サーバーがユーザー名とパスワードを保存する必要があります。これはサーバー側の状態であるため、厳密にはRESTではありません。私の答えを見てください。
jcoffland 2014

3
@jcoffland:どちらの場合も、それは単に真実ではありません。最初のHTTP認証では、サーバーにパスワードを保存する必要はありません。代わりにパスワードのハッシュが保存されます(8ラウンド以上のbcryptが推奨されます)。次に、認証ヘッダーはすべてのリクエストで送信されるため、サーバーには状態がありません。また、保存されているパスワードハッシュを状態と見なすと、保存されている公開キーと同じ状態になります。
Boris B. 14

1
@Boris B.、はい、パスワードはハッシュとして保存されることを理解しています。ハッシュされたパスワードは、依然としてクライアント固有の状態です。私のソリューションで説明されているように、公開鍵を格納することの違いは、認証サーバーの公開鍵が1つしかないことです。これは、ユーザーごとにパスワードハッシュを保存する場合とは大きく異なります。どのようにドレスアップしても、サーバーが各ユーザーのパスワードを保存している場合は、ユーザーの状態ごとに保存され、100%RESTではありません。
jcoffland 2014

7
ユーザーにハッシュ化されたパスワードをサーバーに保存することは、サーバー側の状態と考えるべきではないと思います。ユーザーは、名前、アドレス、ハッシュ化されたパスワードなどの情報を含むリソースです。
Codepunkt 14年

15

@skrebel(http://www.berenddeboer.net/rest/authentication.html)が言及した「非常に洞察に満ちた」記事)では、複雑であるが実際には壊れている認証方法について説明しています。

ページにアクセスしてみてください(認証されたユーザーにのみ表示されることになっています)http://www.berenddeboer.net/rest/site/authenticated.htmlログイン認証情報なしで。

(申し訳ありませんが、回答にはコメントできません。)

RESTと認証は単純に混合しないと思います。RESTはステートレスを意味しますが、「認証済み」はステートです。両方を同じレイヤーに置くことはできません。RESTful擁護者であり、州に不満がある場合は、HTTPSを使用する必要があります(つまり、セキュリティの問題を別のレイヤーに任せます)。


Stripe.comは...ミキシングないRESTと認証上のあなたのコメントにそう言うでしょう
エリック・

ステートレスはサーバーではなくクライアントを指します。クライアントはセッションのすべての状態を記憶し、各リクエストに関連するものを送信できます。
Dobes Vandermeer 2014年

最後に、誰かが何らかの意味を話しますが、公開鍵暗号を使用してステートレス認証が可能です。私の答えを見てください。
jcoffland 2014

1
サーバーには「認証済み」状態はありません。ハイパーメディアを介して情報を受け取り、それと連携して要求されたものを返す必要があります。それ以上でもそれ以下でもありません。リソースが保護されており、認証と承認が必要な場合は、提供されるハイパーメディアにその情報を含める必要があります。リソースを返す前にユーザーを認証することは、サーバーが状態を追跡していることを意味するという概念がどこから来たのかわかりません。ユーザー名とパスワードを提供することは、単により多くのフィルタリングパラメータを提供することと考えることができます。
Michael Ekoka 2014

「RESTと認証は単純に混同しないと思います。」常識のようですね。認証と互換性のないシステム(「認証された」それ自体はもちろん状態です)の有用性は限られています。私たちは皆、実用性と純粋主義の教義の交差点で議論しているように感じます。率直に言って、実用性が勝つべきです。認証に関して状態を回避しようとするゆがみに入ることなく、非常に有益なRESTの側面がたくさんありますね。
Craig

12

RESTful認証には、リクエストのパラメーターとして認証トークンを渡すことが含まれると思います。例としては、apiによるapikeysの使用があります。私はcookieやhttp authの使用が適切であるとは思いません。


CSRFの脆弱性のため、CookieとHTTP認証は避けてください。
Dobes Vandermeer 2014年

@DobesVandermeerあなたが助けることができるなら、あなたは私の質問を見てください。stackoverflow.com/questions/60111743/...
Hemant Metalia

12

2019年2月16日更新

以下で前述したアプローチは、本質的にOAuth2.0の「リソース所有者パスワード資格情報」付与タイプです。これは、起動して実行する簡単な方法です。ただし、このアプローチでは、組織内のすべてのアプリケーションが独自の認証および承認メカニズムを使用することになります。推奨されるアプローチは、「承認コード」付与タイプです。さらに、以下の私の以前の回答では、認証トークンを格納するためにブラウザーのlocalStorageを推奨しました。しかし、私はcookieがこの目的のための正しいオプションであると信じるようになりました。このStackOverflowの回答には、私の理由、認証コード付与タイプの実装方法、セキュリティに関する考慮事項などが詳しく記載されています


RESTサービスの認証には次のアプローチを使用できると思います。

  1. 認証用のユーザー名とパスワードを受け入れるログインRESTful APIを作成します。HTTP POSTメソッドを使用して、キャッシュと転送中のセキュリティのためのSSLを防止します。認証が成功すると、APIは2つのJWTを返します。
  2. クライアント(WebベースのUI)はJWTをローカルストレージに保存し、後続のすべてのAPI呼び出しで「Authorization:Bearer #access token」ヘッダーにアクセストークンを渡します
  3. APIは、署名と有効期限を検証することにより、トークンの有効性をチェックします。トークンが有効な場合は、ユーザー(JWTの「sub」クレームをユーザー名として解釈する)がキャッシュルックアップを使用してAPIにアクセスできるかどうかを確認します。ユーザーがAPIへのアクセスを許可されている場合は、ビジネスロジックを実行します。
  4. トークンの有効期限が切れている場合、APIはHTTP応答コード400を返します
  5. クライアントは400/401を受信すると、「Authorization:Bearer #refresh token」ヘッダーの更新トークンを使用して別のREST APIを呼び出し、新しいアクセストークンを取得します。
  6. 更新トークンを含む呼び出しを受信したら、署名と有効期限を確認して、更新トークンが有効かどうかを確認します。更新トークンが有効な場合は、DBからユーザーのアクセス権キャッシュを更新し、新しいアクセストークンと更新トークンを返します。更新トークンが無効な場合、HTTP応答コード400を返します
  7. 新しいアクセストークンと更新トークンが返された場合は、手順2に進みます。HTTP応答コード400が返された場合、クライアントは更新トークンが期限切れであると見なし、ユーザーにユーザー名とパスワードを要求します
  8. ログアウトの場合、ローカルストレージを削除します

このアプローチでは、30分ごとにユーザー固有のアクセス権の詳細をキャッシュにロードするというコストのかかる操作を行っています。したがって、アクセスが取り消されるか、新しいアクセスが許可された場合、反映されるまでに30分かかるか、ログアウトしてからログインする必要があります。


たとえば、これは、angularで作成された静的Webサイトを持つAPIに使用しますか?そして、モバイルアプリはどうですか?
Yazan Rawashdeh

8

それがその方法です:ログインにOAuth 2.0を使用するます。

OAuthをサポートしている限り、Google以外の認証方法を使用できます。


1
OAuth2はHTTPSなしでは安全ではなく、ステートレスでもありません。
Arnaud Bouchez

4
HTTPSなしでは安全なものはありません。
Craig

1
証明書チェーンが壊れている場合@CraigおよびHTTPSは、より良いためであってもよい、いずれか安全でないかもしれない- en.wikipedia.org/wiki/Bullrun_(decryption_program) ;)
アルノーBouchez

1
@ArnaudBouchez証明書チェーンが壊れていることのメリットを明確にしてください。どこへ行くのか分かりません。;)
Craig

@クレイグリンクをたどって、お楽しみください!この「非常に良い」アプローチは、私のコメントで明らかに皮肉なものでした。ブルランのようなシステムは、私たちの愛する信頼できる政府による「私たち自身の利益」を意味しています。
Arnaud Bouchez

3

鍵の登録に適切なバインディングが含まれる公開鍵インフラストラクチャを使用すると、公開鍵が、否認防止を保証する方法で割り当てられた個人に確実にバインドされます。

http://en.wikipedia.org/wiki/Public_key_infrastructureを参照してください。適切なPKI標準に従うと、盗まれたキーを不正に使用した人物またはエージェントを特定してロックアウトできます。エージェントが証明書を使用する必要がある場合、バインディングはかなり厳しくなります。巧妙で動きの速い泥棒は逃げることができますが、より多くのパンくずを残します。


2

私の理解からこの質問に答えるために...

システム内のユーザーを実際に追跡または管理する必要がないように、RESTを使用する認証システム。これは、HTTPメソッドPOST、GET、PUT、DELETEを使用して行われます。これらの4つの方法を採用し、データベースの相互作用の観点からCREATE、READ、UPDATE、DELETEと見なします(ただし、Webではアンカータグが現在サポートしているため、POSTとGETを使用します)。したがって、POSTとGETを作成/読み取り/更新/削除(CRUD)として扱うと、達成しているCRUDのアクションを推測できるように、Webアプリケーションでルートを設計できます。

たとえば、Ruby on Railsアプリケーションでは、ログインしているユーザーがhttp://store.com/account/logoutにアクセスした場合にWebアプリケーションを構築できます。アクセスすると、そのページのGETがログアウトしようとしているユーザーとして表示されるできます。 。Railsコントローラーで、ユーザーをログアウトさせてホームページに送り返すアクションを作成します。

ログインページでGETを実行すると、フォームが生成されます。ログインページのPOSTはログイン試行として表示され、POSTデータを取得してログインに使用します。

私にとっては、データベースの意味にマップされたHTTPメソッドを使用し、セッションIDを渡したりセッションを追跡したりする必要がないことを念頭に置いて認証システムを構築する習慣です。

私はまだ学習中です-私が間違っていると言った何かを見つけたら私を修正してください、そしてあなたがもっと学ぶならここに投稿してください。ありがとう。


2

Webアプリケーションを保護するために有効なヒント

アプリケーションを保護したい場合は、HTTPではなくHTTPSを使用することから始めてください。これにより、ユーザーとユーザーの間で送受信されるデータを盗聴することを防ぎ、データを保持するのに役立つ安全なチャネルが作成されます。機密情報を交換しました。

JWT(JSON Webトークン)を使用してRESTful APIを保護できます。これには、サーバー側のセッションと比較して多くの利点があります。主な利点は次のとおりです。

1- APIサーバーが各ユーザーのセッションを維持する必要がないため、よりスケーラブルです(多くのセッションがある場合、これは大きな負担になる可能性があります)。

2- JWTは自己完結型であり、たとえばユーザーロールを定義するクレームを持ちます&アクセスできるもの&日付と有効期限日に発行されます(それ以降はJWTは無効になります)

3- JWTを使用したリクエストが認証されたサーバーにヒットするたびに、セッションデータを共有したり、セッションを同じサーバーにルーティングするようにサーバーを構成したりする必要がないため、ロードバランサー全体での処理がより簡単になります。 &承認済み

4- DBへの負担が軽減され、リクエストごとにセッションIDとデータを常に保存および取得する必要がなくなります。

5- JWTに署名するために強力な鍵を使用する場合、JWTを改ざんできないため、ユーザーセッションを確認する必要なく、リクエストが送信されたJWTのクレームを信頼でき、承認されているかどうかを確認できます、JWTを確認するだけで、このユーザーが誰が何をできるかを知る準備が整います。

多くのライブラリは、ほとんどのプログラミング言語でJWTを簡単に作成および検証する方法を提供します。たとえば、node.jsで最も人気のあるものの 1つはjsonwebtokenです。

REST APIは通常、サーバーをステートレスに保つことを目的としているため、各リクエストは自己完結型の承認トークン(JWT)で送信されるため、JWTその概念とより互換性がありますがユーザーセッションを追跡する必要がなく、で送信されるため、あります。サーバーはステートフルなので、ユーザーとその役割を記憶しますが、セッションも広く使用されており、必要に応じて検索できるプロがいます。

注意すべき重要な点の1つは、HTTPSを使用してJWTをクライアントに安全に配信し、安全な場所(ローカルストレージなど)に保存する必要があることです。

このリンクから JWTの詳細を学ぶことができます

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