REST APIをレガシーPHPサイトに追加する作業を行っています。これは、内部アプリのエンドポイントを提供するためです。私はものをデザインし、何をサポートし、何をサポートしません。
このAPIに追加する必要があるのは、ログインして特定のユーザーとしてアクションを実行する方法です。このサイトは何年も前に構築されたものであり、必ずしもその時点でのベストプラクティスではありません。そのため、残念ながら私はこれを行う方法が少し制限されています。これはすべて、PHP 5.4とMySQL 5.6で実行する必要があります。
私はこのための一般的な設計を読んでおり、OAuth1/2は最も一般的な標準のように見えます。しかし、これは私の目的にとっては大げさすぎるように思えます。なぜなら、これには必要のないさまざまな機能があり、実装が非常に複雑だからです。
代わりに、私はこのようなことをすることを計画しています:
get_session
ランダムセッションIDを生成するAPIエンドポイントは、それをデータベースのテーブルに保存し、クライアントに返します。login
エンドポイントにリクエストを送信し、ユーザー名、パスワード、およびセッションIDを(明らかにHTTPS経由で)送信することにより認証します。logout
エンドポイントにリクエストを送信し、サーバーはユーザーアカウントとの関連付けを削除します。これは合理的な設計ですか?それほど洗練されたものではないことは明らかですが、大きな手間やサードパーティのライブラリを必要とせずに実装できるものを探しています。
RESTの概念としての主要な点の1つは、RESTエンドポイントのリソースを水平方向にスケーリングしやすくするために、セッション状態の使用を避けることです。 PHPの$_SESSION
質問で概説したように、スケールアウトしたい場合に共有セッションストレージを実装しなければならないという難しい立場にいることに気づくでしょう。
OAuthがあなたのやりたいことのための好ましい方法でしょうが、完全な実装はあなたが入れたいと思うよりも多くの仕事でありえます。しかし、あなたは半分の何かを切り分けることができます。あなたはおそらく同様のソリューションを見たことがあります。
このようにして、「セッションレス」REST理想を維持し、交換のどの部分でも実際にシークレットを送信することはありません。
クライアントの例:
$token = "Bmn0c8rQDJoGTibk"; // base64_encode(random_bytes(12));
$secret = "yXWczx0LwgKInpMFfgh0gCYCA8EKbOnw"; // base64_encode(random_bytes(24));
$stamp = "2017-10-12T23:54:50+00:00"; // date("c");
$sig = hash_hmac('SHA256', $stamp, base64_decode($secret));
// Result: "1f3ff7b1165b36a18dd9d4c32a733b15c22f63f34283df7bd7de65a690cc6f21"
$request->addHeader("X-Auth-Token: $token");
$request->addHeader("X-Auth-Signature: $sig");
$request->addHeader("X-Auth-Timestamp: $stamp");
サーバーの例:
$token = $request->getToken();
$secret = $auth->getSecret($token);
$sig = $request->getSignature();
$success = $auth->validateSignature($sig, $secret);
タイムスタンプをナンスとして使用することに決めた場合、リプレイ攻撃を防ぐために最後の数分以内に生成されたタイムスタンプのみを受け入れる必要があることに注意してください。他のほとんどの認証方式では、リソースパス、ヘッダーデータのサブセットなど、署名されたデータに追加のコンポーネントが含まれ、単一の要求にのみ適用されるように署名をさらにロックダウンします。
一意のトークンを生成し、それを通信に使用する必要があると思います。基本的に:
login
リソースにユーザー名/パスワードを送信します。sessions
テーブルに保存して、logged_in = TRUE
などのステータス更新とともにユーザーに送り返します。token
フィールド(POST
フィールドまたはGET
パラメーターとして)を含める必要があります。この時点で、RESTを使用して、すべてにPOST
リクエストのみを使用し、operation
をPOST =フィールド。これはトークンをURLに追加しないため、履歴、ルーターなどを閲覧するWebにトークンを登録できます。403 Forbidden
やlogged_in = FALSE
などのエラーメッセージを返すだけです。システムは、クライアントで生成されたunique id
などの別のデータを送信して、トークンで送信し、サーバー側でチェックする必要がある場合もあります。
計画のポイントは、基本的にOAuthの基本機能です。要件によって異なります。 APIが内部使用専用である場合、HMAC-SHA認証を使用して秘密鍵を送信できます。
さて、最初からクッキーを発明する方法と、それらをデータベースに保存する方法をたくさん書きました。
同時に、セキュリティデータ転送用のユーザー名、パスワード、およびHTTPSが既にあります。なぜクッキーだけを使用しないのですか?