web-dev-qa-db-ja.com

トークンを使用したRESTful API認証の実装(Yii / Yii2)

私は、モバイルアプリケーションで使用されるAPIをYii 1.xで構築しています。プロセスの一部には、以下のJSONリクエストを使用したログイン(ユーザー名とパスワードを使用)が含まれます。

//ユーザー名とパスワードで送信されたリクエスト

{
"request" : {
    "model" : {
        "username" : "bobbysmith",
        "password" : "mystrongpassword"
    }
  }
}

//ログインに成功した場合、次の応答を返します

{
"response": {
    "code": 200,
    "message": "OK",
    "model": {
        "timestamp": 1408109484,
        "token": "633uq4t0qdtd1mdllnv2h1vs32"
    }
 }
}

このトークンは非常に重要です。ユーザーがアプリにログインしたら、ログインが必要な他のページにアクセスできるようにします。モバイルアプリにこのトークンを保存し、同じ場合は633uq4t0qdtd1mdllnv2h1vs32トークンは、認証されたリクエストであるとしてこの後続のリクエスト内で見つかります(このユーザー「bobbysmith」の場合)。

私はこれを行う最善の方法について少し確信が持てず、いくつかの研究を行ってきましたが、oAuthがHTTPSを介した基本認証とともに数回言及されています。

簡単に言うと...

  1. モバイルアプリのホームページで、ユーザーはユーザー名とパスワードを使用して正しくログインします。これにより、APIにリクエストが送信されます。
  2. これは、現在のタイムスタンプとすべての重要なトークンを含む成功した応答(上記を参照)を返します。
  3. 同じユーザーは、このトークンが必要な別のアプリのページ/ビューに移動します。a)要求され、b)これが一致する場合、そのユーザーを認証します(たとえば、アカウントを編集できるようになります)。
  4. ユーザーが「ログアウト」をクリックすると、このトークンは削除されます(そして、マイアカウントなどにアクセスできるようになります)。基本的にはトークンベースの認証システムです。

誰でもこれを達成するための最良の方法を説明できますか?説明した内容が100%明確でない場合はお知らせください。詳細をお知らせします。

私はPHPを使用していますが、Yii 1.xソリューションは、現在のAPIが使用して構築されているものであるため、理想的です。

一言で言えば、アプリはサーバーへのすべてのリクエストにペイロードまたはヘッダーにトークンが含まれていることを保証するため、このトークンはevery以降の投稿で取得できます。ログアウトすると、このトークンは単に削除されますOR null /空に設定

21
Zabs

セキュリティインターフェイスの処理に関する情報

すべての適切な(RESTful)認証項目を一度に提供するソリューションに焦点を当てます。

  • [〜#〜] ssl [〜#〜](最も重要、そうでない場合は「HTTP-Auth」の意味が少なくなり、誰でも読めるようになりますリクエストヘッダー/本文を出力 中間者攻撃
  • oAuth(またはより良いoAuth2!)
  • HTTP-Auth
  • トークン(限られたライフタイム、更新を含み、IP/DeviceUIDチェックロジックを含む->モバイルの場合!)
  • 塩生成パスワード
  • ID/ENV/CLIENTチェックまたはその他のカスタムHTTPヘッダー
  • データ操作を防止するためのリクエストおよびレスポンスの暗号化されたボディデータ

ヒント:個人ユーザーデータは常に暗号化する必要があります!


たぶん解決策

上記では、セキュリティインターフェイスに関する標準情報を確認できます。永続的なセキュリティを確保するために、次のパートのように試すことができます。 AppSidePersitenceについてはわかりません。たぶんそのsqlLiteかそのようなもの。そのため、Yiiで行ったように、コードベースのDBスキーマを示しません。時間とトークンを保存するには、Yiiアプリケーション(バックエンド)内およびアプリ(クライアント)内にストレージ/永続性が必要です。

YiiDBModel

enter image description here

-- -----------------------------------------------------
-- Table `mydb`.`user`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`user` (
  `id` INT NOT NULL,
  `username` VARCHAR(255) NOT NULL,
  `password` VARCHAR(255) NOT NULL,
  `lastLogin` DATETIME NULL,
  `modified` DATETIME NULL,
  `created` DATETIME NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB;

----------------------------------------------------
-- Table `mydb`.`authToken`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`authToken` (
  `id` INT NOT NULL,
  `userId` INT NOT NULL,
  `token` VARCHAR(255) NOT NULL,
  `created` DATETIME NOT NULL,
  PRIMARY KEY (`id`, `userId`),
  INDEX `fk_authToken_user_idx` (`userId` ASC),
  UNIQUE INDEX `token_UNIQUE` (`token` ASC),
  CONSTRAINT `fk_authToken_user`
    FOREIGN KEY (`userId`)
    REFERENCES `mydb`.`user` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

AppPersitenceModel

enter image description here

トークンを正しく処理し、ログインのセキュリティを確保する

  1. Yii-Application側で生成したトークンは、YiiApp-Databaseの「作成された」日時とともに保存されます(表authTokenを参照)。各ユーザーには、正しい「ログイン」リクエストの後に生成される「トークン」が1つしかありません。この方法では、「ログイン」中にトークンを確認する必要はありません。スキーマによって定義される「トークン」は一意です!履歴データ(期限切れの古いトークン)を処理する必要はないと思います。
  2. ユーザーログインがYiiによって「成功」として検証されると、YiiApp-DBに保存される現在のタイムスタンプで新しいユーザートークンを生成します。YiiAppで設定する必要がありますたとえば、「タイムスタンプ」を使用する場合、現在のタイムスタンプに追加される「有効期限」:現在のタイムスタンプは1408109484で、有効期限は3600(これは3600秒= 1h)です。..API経由で送信される有効期限は(1408109484+3600)です。ヒント:"code": 200などの属性を送信する必要はありません。応答コードはRequests/Response-Header-Dataに含まれています。

    ** 200 OK Response-Example、ユーザーログインが成功した後、計算された「期限切れ」日付を保持します:**

     {
        "error": null,
        "content": {
            "expires": 1408109484,
            "token": "633uq4t0qdtd1mdllnv2h1vs32"
        }
    }
    
  3. 重要:セキュリティで保護するすべてのリクエストは、生成されたユーザー「トークン」で送信する必要があります。おそらくdeviceStorageに保存されます。 「ログイン状態」を処理できます。 HTTP-Response-Codes rightを使用する場合は本当にRESTfulです。たとえば、200 OK(すべてが正常な場合)または401(認証されていない、ユーザーがログに記録されません)またはセッションの有効期限が切れています)。 Yii side。のUser-Requestを検証する必要があります。着信要求からトークンを読み取り、データベース内の特定のトークンにより検証し、「作成済み」-DBを現在の着信要求と比較します-時間(HTTPリクエスト)。

    **リクエスト例、セキュリティリクエストのデフォルトスキーマ:**

    {
        "token": "633uq4t0qdtd1mdllnv2h1vs32"
        "content": {
            "someDataYouNeed" : null
        }
    }
    

    ** 401不正な応答-例、トークンの有効期限が切れています:**

    {
        "error": 1, // errorCode 1: token is expired
        "content": {
            "someDataYouNeed" : null
        }
    }
    

    ** 401不正な応答-例、ユーザーはログインしていません(YiiDBにトークンが存在しません):**

    {
        "error": 2, // errorCode 2: user is not logged in
        "content": {
            "someDataYouNeed" : null
        }
    }
    
  4. ユーザーセッションを維持しますか?それは非常に簡単です。 authToken- Tableの "created" -Dateを現在のリクエスト時間に更新するだけです。そのたびに、ユーザーから有効なリクエストが送信されました。そのようにして、ユーザーがまだアクティブな場合、セッションは期限切れになりません。 DBのexpires- Dateフィールドを更新する前に、DB-Tokenの有効期限が切れていないことを確認してください。セッションの有効期限が切れている間にリクエストが送信されない場合、キープアライブはできなくなります。

    申し訳ありませんが、PHPコードの追加は多すぎます。

55
lin

ネイティブモバイルアプリ向けに構築する場合、賢明なことは、Cookieベースのソリューションではなく、ネイティブメモリ(iOSキーチェーンなど)のセキュリティに依存することです。それ以外の場合は、説明した方法で問題ないようです。ペイロードがSSLを介して送信されている限り、トークンがPUTにあるかPOSTにあるかは問題ではありません。トークン管理(つまり有効期限)は、ビジネス上の決定です。バックエンドは、トークンを説明してデータベースに保持し、何らかの理由でトークンが無効になったときに削除し、クライアントアプリにメッセージを返してログアウトモード/再要求資格情報に戻すようにします。

編集:多作なフィル・スタージョンからのこの素晴らしいタットをチェックしてください。また、CIでRESTful APIを構築するための優れたCIライブラリーもあります。

http://philsturgeon.uk/blog/2013/07/building-a-decent-api

http://code.tutsplus.com/tutorials/working-with-restful-services-in-codeigniter--net-8814

0
Mike Miller

おそらくこの時点までにYii2に切り替えたので、今後の参考のために、最もクリーンなソリューションはRESTful APIに含まれるクラスを使用するか、任意のフレームワークでそれらを実装することです。

ソース: HttpBearerAuth.php

利点は この記事 で完全に説明されていますが、要約するために、GETを使用してrequest headersでソリューションを使用することをお勧めしますパラメーターはログに保存される可能性があり、SSLを使用しない場合は基本認証パスワードが簡単に傍受される可能性があります(そうすべきです!)

0
Razvan Grigore