-
11-07-2019 - |
質問
RESTful認証とはどういう意味で、どのように機能しますか? Googleで良い概要を見つけることができません。私の唯一の理解は、URLでセッションキー(記憶)を渡すことですが、これは恐ろしく間違っている可能性があります。
解決
RESTfulクライアントサーバーアーキテクチャで認証を処理する方法は、議論の問題です。
一般に、SOA over HTTPの世界では次の方法で実現できます。
- HTTPS経由のHTTP基本認証;
- Cookieとセッション管理;
- 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を介して)サーバーに送信されるという事実(パスワードは、キーボード入力中にクライアント側のみに残し、安全なハッシュとして保存する方が安全である必要があります)サーバー)。
ダイジェスト認証を使用できますが、HTTPSも必要です。これは、< a href = "http://en.wikipedia.org/wiki/Man-in-the-middle_attack" rel = "noreferrer"> MiM またはリプレイ攻撃であり、HTTP固有です。
Cookieを介したセッション
正直に言うと、サーバーで管理されるセッションは真にステートレスではありません。
1つの可能性は、Cookieコンテンツ内のすべてのデータを維持することです。また、設計上、Cookieはサーバー側で処理されます(実際、クライアントは、このCookieデータを解釈しようとさえしません。リクエストが連続するたびにサーバーに返します)。ただし、このCookieデータはアプリケーションの状態データであるため、クライアントはサーバーではなく、純粋なステートレスの世界で管理する必要があります。
GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: theme=light; sessionToken=abc123
Cookie技術自体はHTTPリンクされているため、プロトコルに依存しない、真の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エンコードの前に署名を行う必要があります クエリ文字列。
この手法は、おそらくStatelesとの互換性が高い
他のヒント
人々が「HTTP認証」を熱狂的に叫んでいるかどうかは疑問です。 RESTを使用して(マシンツーマシンWebサービスの代わりに)ブラウザーベースのアプリケーションを作成しようとしました(攻撃は意図されていません-合併症に直面したことはないと思います)。
ブラウザで表示するHTMLページを生成するRESTfulサービスでHTTP認証を使用したときに見つかった問題は次のとおりです。
- ユーザーは通常、見苦しいブラウザー製のログインボックスを取得しますが、これは非常にユーザーフレンドリーではありません。パスワード取得、ヘルプボックスなどを追加することはできません。
- ログアウトまたは別の名前でのログインは問題です。ウィンドウを閉じるまで、ブラウザは認証情報をサイトに送信し続けます
- タイムアウトが難しい
これらのポイントごとに取り組む非常に洞察力のある記事はこちらですが、この結果はブラウザ固有のJavaScriptハッカーの多く、回避策の回避策など。そのため、前方互換性もないため、新しいブラウザがリリースされるたびに定期的なメンテナンスが必要になります。私はそのきれいで明確なデザインを考慮していません。さらに、RESTバッジを熱心に友人に見せることができるように、多くの余分な作業と頭痛の種だと感じています。
クッキーは解決策だと思います。しかし、待ってください、クッキーは悪ですよね?いいえ、そうではありません。Cookieがよく使用される方法は悪です。 Cookie自体は、ブラウザが閲覧中に追跡するHTTP認証情報と同様に、クライアント側の情報の一部にすぎません。また、このクライアント側の情報は、HTTP認証情報と同様に、リクエストごとにサーバーに送信されます。概念的には、唯一の違いは、このクライアント側の状態の content は、応答の一部として server によって決定できることです。
次のルールだけでセッションをRESTfulリソースにすることにより:
- セッションは、キーをユーザーID(および場合によってはタイムアウトのlast-action-timestamp)にマッピングします
- セッションが存在する場合、それはキーが有効であることを意味します。
- ログインは/ sessionsへのPOSTを意味し、新しいキーがCookieとして設定されます
- ログアウトとは、/ sessions / {key}を削除することです(POSTがオーバーロードされているため、ブラウザーであり、HTML 5はまだまだ先のことです)
- 認証は、リクエストごとにCookieとしてキーを送信し、セッションが存在して有効かどうかを確認することで行われます
HTTP認証との唯一の違いは、認証キーがサーバーによって生成され、クライアントが入力された資格情報から計算するのではなく、送信を続けるクライアントに送信されることです。
converter42は、https(使用する必要がある)を使用する場合、Cookieにセキュアフラグを設定して、認証情報が非セキュア接続を介して送信されないようにすることが重要です。素晴らしい点は、自分で見たことがないことです。
これは十分に機能する十分なソリューションであると感じていますが、このスキームの潜在的な穴を特定するためのセキュリティの専門家ではないことを認めなければなりません-私が知っているのは、何百もの非RESTful Webアプリケーションが基本的に同じログインプロトコル(PHPの$ _SESSION、Java EEのHttpSessionなど)。 Cookieヘッダーのコンテンツは、accept-languageが翻訳リソースなどにアクセスするために使用されるのと同じように、単にサーバー側のリソースをアドレス指定するために使用されます。私はそれが同じだと感じていますが、他の人もそうではないでしょうか?どう思いますか?
このトピックについては、すでに良い人々がここで十分に述べています。しかし、ここに私の2セントがあります。
相互作用には2つのモードがあります:
- 人間対機械(HTM)
- マシンツーマシン(MTM)
マシンは共通の分母であり、REST APIとして表され、アクター/クライアントは人間またはマシンのいずれかです。
今、真のRESTfulアーキテクチャでは、ステートレスの概念は、すべての関連するアプリケーションの状態(クライアント側の状態を意味する)がすべてのリクエストで提供される必要があることを意味します。関連するということは、REST APIが要求を処理して適切な応答を提供するために必要なものを意味します。
これを人間から機械へのアプリケーションのコンテキストで考えると、「ブラウザベース」 Skrebbelが上記で指摘しているように、これは、ブラウザーで実行されている(Web)アプリケーションが、バックエンドREST APIに対して行う各要求でその状態と関連情報を送信する必要があることを意味します。
これを考慮してください:データ/情報プラットフォームに公開されたREST APIの資産があるとします。おそらく、すべてのデータキューブを処理するセルフサービスBIプラットフォームがあります。ただし、(1)Webアプリ、(2)モバイルアプリ、および(3)サードパーティアプリケーションを介して、(人間の)顧客にこれにアクセスしてもらいたいと考えています。最終的に、MTMのチェーンでさえHTMにつながります-そうです。したがって、ユーザーは情報チェーンの頂点に留まります。
最初の2つのケースでは、人間とマシンの相互作用のケースがあり、情報は実際に人間のユーザーによって消費されます。最後のケースでは、REST APIを使用するマシンプログラムがあります。
認証の概念は全面的に適用されます。 REST APIが統一された安全な方法でアクセスされるように、これをどのように設計しますか?私がこれを見る方法には、2つの方法があります:
Way-1:
- 最初からログインはありません。すべてのリクエストがログインを実行します
- クライアントは、識別パラメーター+特定の要求を送信します 各リクエストのパラメータ
- REST APIはそれらを取得し、向きを変え、ユーザーストアにpingを送信します (それが何であれ)認証を確認します
- 認証が確立されると、リクエストを処理します。そうでなければ、拒否 適切なHTTPステータスコード
- 上のすべてのREST APIのすべてのリクエストに対して上記を繰り返します カタログ
Way-2:
- クライアントは認証リクエストで始まります
- ログインREST APIはこのようなリクエストをすべて処理します
- 認証パラメータ(APIキー、uid / pwd、またはあなたが ユーザーストア(LDAP、AD、またはMySQL DBなど)に対する認証を選択して検証します
- 検証された場合、認証トークンを作成し、それを クライアント/呼び出し元
- 次に、呼び出し元はこの認証トークンを送信し、特定のパラメーターを要求します ログアウトされるか、リースの期限が切れるまで、他のビジネスREST APIへの後続のすべてのリクエスト
明らかに、Way-2では、REST APIにはトークンが有効であると認識して信頼する方法が必要です。ログインAPIが認証確認を実行したため、その「valet key」はカタログ内の他のREST APIによって信頼される必要があります。
これは、もちろん、認証キー/トークンを保存し、REST API間で共有する必要があることを意味します。この共有された信頼できるトークンリポジトリは、他の組織のREST APIが相互に信頼できるように、ローカル/フェデレーションできます。
しかし、私は脱線します。
ポイントは、「状態」です(クライアントの認証ステータスについて)は、すべてのREST APIが信頼の輪を作成できるように維持および共有する必要があります。これを行わない場合、つまりWay-1の場合、着信するすべての要求に対して認証行為を実行する必要があることを受け入れる必要があります。
認証の実行は、リソースを大量に消費するプロセスです。着信リクエストごとに、ユーザーストアに対してSQLクエリを実行して、uid / pwdの一致をチェックすることを想像してください。または、ハッシュマッチを暗号化して実行するには
これは、完全かつ完全なRESTful認証ソリューションです。
- 認証サーバーで公開/秘密キーのペアを作成します。
- 公開鍵をすべてのサーバーに配布します。
-
クライアントが認証するとき:
3.1。次を含むトークンを発行します。
- 有効期限
- ユーザー名(オプション)
- ユーザーIP(オプション)
- パスワードのハッシュ(オプション)
3.2。秘密鍵でトークンを暗号化します。
3.3。暗号化されたトークンをユーザーに送り返します。
-
ユーザーがAPIにアクセスするときは、認証トークンも渡す必要があります。
- サーバーは、認証サーバーの公開キーを使用してトークンを復号化することにより、トークンが有効であることを確認できます。
これはステートレス/レストフル認証です。
パスワードハッシュが含まれている場合、ユーザーは暗号化されていないパスワードも認証トークンとともに送信することに注意してください。サーバーは、ハッシュを比較することで、パスワードが認証トークンの作成に使用されたパスワードと一致したことを確認できました。 HTTPSのようなものを使用した安全な接続が必要です。クライアント側のJavascriptは、ユーザーのパスワードを取得して、メモリまたはCookieにクライアント側に保存し、場合によってはサーバーの公開キーで暗号化できます。
正直に言って、私はここで素晴らしい答えを見ましたが、少し気になるのは、誰かがステートレスの概念全体を極端なものにして、独断的になることです。純粋なオブジェクト指向だけを受け入れたいと思っていた古いSmalltalkファンを思い起こさせます。何かがオブジェクトではない場合、あなたはそれを間違っています。ちょっと待ってください。
RESTfulアプローチは、あなたの人生を楽にし、セッションのオーバーヘッドとコストを削減することを想定しています。それがもはや意図された利益を提供しない極端な場合、あなたはそれを間違っています。今日の最高の言語のいくつかは、関数型プログラミングとオブジェクト指向の両方を備えています。
問題を解決する最も簡単な方法が認証キーをCookieに保存し、HTTPヘッダーで送信することである場合、それを実行します。悪用しないでください。セッションが大きくて大きくなるとセッションが悪くなります。セッションがすべてキーを含む短い文字列である場合、大したことは何ですか?
コメントの修正を受け入れることはできますが、(これまでのところ)サーバーにハッシュの大きな辞書を保持するのを避けるために、私たちの生活を悲惨にすることの意味がわかりません。
何よりもまず、RESTful Webサービスは STATELESS (つまり、 SESSIONLESS )です。したがって、RESTfulサービスには、セッションまたはCookieの概念は含まれておらず、含まれるべきではありません。 RESTfulサービスで認証または許可を行う方法は、RFC 2616 HTTP仕様で定義されているHTTP Authorizationヘッダーを使用することです。すべての要求にはHTTP Authorizationヘッダーが含まれている必要があり、要求はHTTP(SSL)接続を介して送信される必要があります。これは、認証を行い、HTTP RESTful Webサービスでリクエストの承認を検証する正しい方法です。シスコシステムズのCisco PRIME Performance Managerアプリケーション用にRESTful Webサービスを実装しました。そして、そのWebサービスの一部として、認証/承認も実装しました。
ルーベンスゴメス。
「セッションキー」についてではありません。一般に、RESTのすべての制約内で実行されるセッションレス認証を指すために使用されます。各リクエストは自己記述的であり、サーバー側のアプリケーションの状態なしでリクエストを独自に承認するのに十分な情報を伝えます。
これにアプローチする最も簡単な方法は、 RFC 2617にあるHTTPの組み込み認証メカニズムから始めることです。 / a>。
@skrebelが言及した「非常に洞察に富んだ」記事( http://www.berenddeboer.net /rest/authentication.html ) 複雑ではあるが本当に壊れた認証方法について説明しています。
ページ(認証されたユーザーにのみ表示されることになっている)にアクセスすることができます http://www.berenddeboer.net/rest/site/authenticated.html (ログイン資格情報なし)
(回答についてコメントできません。)
RESTと認証は単純に混在しないと思います。 RESTはステートレスを意味しますが、「認証済み」はステートです。両方を同じレイヤーに置くことはできません。あなたがRESTfulの擁護者であり、州に眉をひそめている場合は、HTTPSを使用する必要があります(つまり、セキュリティ問題を別のレイヤーに任せます)。
安らかな認証には、認証トークンをパラメータとしてリクエストに渡すことが含まれると思います。例は、apiによるapikeysの使用です。 CookieまたはHTTP認証の使用が適切であるとは思わない。
2019年2月16日に更新
前述のアプローチは、本質的に「リソース所有者のパスワード認証情報」です。付与タイプ OAuth2.0 。これは、起動して実行する簡単な方法です。ただし、このアプローチでは、組織内のすべてのアプリケーションが独自の認証および承認メカニズムになります。推奨されるアプローチは、「承認コード」です。付与タイプ。さらに、以下の以前の回答では、認証トークンを保存するためにブラウザーlocalStorageを推奨しました。ただし、この目的にはCookieが適切な選択肢であると信じるようになりました。 このStackOverflowの回答に、理由、認証コード付与タイプの実装アプローチ、セキュリティの考慮事項などを詳しく説明しています。
RESTサービス認証には次のアプローチを使用できると思います:
- 認証用のユーザー名とパスワードを受け入れるログインRESTful APIを作成します。 HTTP POSTメソッドを使用して、転送中のセキュリティのためにキャッシュとSSLを防止します 認証に成功すると、APIは2つのJWTを返します-1つのアクセストークン(短い有効期間、たとえば30分)と1つのリフレッシュトークン(長い有効期間、たとえば24時間)
- クライアント(WebベースのUI)はJWTをローカルストレージに保存し、以降のすべてのAPI呼び出しで「Authorization:Bearer #access token」のアクセストークンを渡します。ヘッダー
- APIは、署名と有効期限を確認することにより、トークンの有効性をチェックします。トークンが有効な場合、ユーザー(JWTの「sub」クレームをユーザー名として解釈する)がキャッシュルックアップでAPIにアクセスできるかどうかを確認します。ユーザーがAPIへのアクセスを許可されている場合は、ビジネスロジックを実行します
- トークンの有効期限が切れている場合、APIはHTTP応答コード400を返します
- クライアントは、400/401を受信すると、「Authorization:Bearer #refresh token」の更新トークンを使用して別のREST APIを呼び出します。新しいアクセストークンを取得するヘッダー。
- 更新トークン付きの呼び出しを受信したら、署名と有効期限を確認して、更新トークンが有効かどうかを確認します。更新トークンが有効な場合、DBからユーザーのアクセス権キャッシュを更新し、新しいアクセストークンと更新トークンを返します。更新トークンが無効な場合、HTTP応答コード400を返します
- 新しいアクセストークンと更新トークンが返された場合、手順2に進みます。HTTP応答コード400が返された場合、クライアントは更新トークンの有効期限が切れていると見なし、ユーザーにユーザー名とパスワードを要求します
- ログアウトするには、ローカルストレージを消去します
このアプローチでは、ユーザー固有のアクセス権の詳細を30分ごとにキャッシュにロードするという高価な操作を行っています。そのため、アクセスが取り消された場合、または新しいアクセスが許可された場合、反映するのに30分かかるか、ログアウトしてからログインします。
それがその方法です:ログインにOAuth 2.0を使用する。
OAuthをサポートしている限り、Google以外の認証方法を使用できます。
私の理解からこの質問に答えるには...
システム内のユーザーを実際に追跡または管理する必要がないように、RESTを使用する認証システム。これは、HTTPメソッドのPOST、GET、PUT、DELETEを使用して行われます。これら4つのメソッドを使用して、データベースの相互作用の観点から、CREATE、READ、UPDATE、DELETEとして考えます(ただし、Webでは、アンカータグが現在サポートしているため、POSTとGETを使用します)。したがって、POSTとGETをCREATE / READ / UPDATE / DELETE(CRUD)として扱うと、CRUDのどのアクションが達成されているかを推測できるWebアプリケーションのルートを設計できます。
たとえば、Ruby on Railsアプリケーションでは、ログインしているユーザーが http://store.com/account/logout を実行すると、そのページのGETは、ログアウトを試みるユーザーとして表示できます。 Railsコントローラーでは、ユーザーをログアウトさせてホームページに送り返すアクションを作成します。
ログインページでGETを実行すると、フォームが生成されます。ログインページのPOSTはログイン試行として表示され、POSTデータを取得してそれを使用してログインします。
私にとっては、データベースの意味にマッピングされたHTTPメソッドを使用し、セッションIDを渡したりセッションを追跡したりする必要がないことを念頭に置いて認証システムを構築することです。
私はまだ学んでいます-私が間違っていると言ったことを見つけたら私を修正してください、そしてあなたがもっと学ぶならここに戻ってそれを投稿してください。ありがとう。
キーの登録に適切なバインドが含まれる公開キーインフラストラクチャを使用すると、公開キーが拒否されないことを保証する方法で割り当てられた個人にバインドされます。
http://en.wikipedia.org/wiki/Public_key_infrastructure を参照してください。適切なPKI標準に従っている場合、盗まれたキーを不適切に使用している人またはエージェントを特定し、ロックアウトできます。エージェントが証明書を使用する必要がある場合、バインディングはかなり厳しくなります。巧妙で動きの速い泥棒は逃げることができますが、より多くのパン粉を残します。
任意のWebアプリケーションを保護するための有効なヒント
アプリケーションをセキュリティで保護する場合は、 HTTPではなくHTTPSを使用して確実に開始する必要があります 。これにより、セキュリティで保護されたチャネルを作成できます。返送されたデータの盗聴を防ぐユーザーユーザーに&amp;交換されるデータの機密保持に役立ちます。
JWT(JSON Web Tokens)を使用してRESTful APIを保護できます。これには、サーバー側セッションと比較した場合に多くの利点があります。利点は主に次のとおりです。
1- APIサーバーは各ユーザーのセッションを維持する必要がないため、よりスケーラブルです(多くのセッションがある場合は大きな負担になる可能性があります)
2- JWTは自己完結型です&amp; &amp;などのユーザーロールを定義するクレームがあります。彼がアクセスできるもの&amp;日付で発行&amp;有効期限(それ以降はJWTは無効になります)
3-ロードバランサーとアンプ間での処理が簡単セッションデータを共有したり、セッションを同じサーバーにルーティングするようにサーバーを構成したりする必要がないため、複数のAPIサーバーがある場合は、JWTを含むリクエストがサーバーにヒットするたびに認証できます。承認済み
4- DBへの負荷が少なくなり、常に&amp;を保存する必要がなくなります。セッションIDを取得&amp;各リクエストのデータ
5-強力なキーを使用してJWTに署名する場合、JWTを改ざんすることはできません。したがって、ユーザーセッションを確認することなく、リクエストとともに送信されるJWTのクレームを信頼できます。彼が許可されているかどうかに関係なく、JWTと誰が&amp;このユーザーができること。
多くのライブラリは、&amp;ほとんどのプログラミング言語でJWTを検証します。たとえば、node.jsで最も人気のあるものの1つは jsonwebtoken
REST APIは一般にサーバーをステートレスに保つことを目的としているため、JWTはそのコンセプトとの互換性がより高い。 >サーバーがユーザーを記憶するようにサーバーをステートフルにするセッションと比較して、サーバーがユーザーセッションを追跡する必要がないしかし、彼の役割は、セッションも広く使用されています&amp;必要に応じて検索できるプロがいます。
注意すべき重要な点は、HTTPS&amp;を使用してクライアントにJWTを安全に配信する必要があることです。安全な場所(ローカルストレージなど)に保存します。
JWTの詳細については、このリンクから
をご覧ください。