web-dev-qa-db-ja.com

PHPFoxで開発されたWebサイトのリソース(関数やデータ)にアクセスするための「トークンベースの認証」を安全に実装する方法

PHPFoxで開発されたWebサイトのコードのメソッドとリソースを使用したい。

基本的に、iPhone/Android、リクエストを取得し、PHPFoxコードからそれぞれの関数に渡し、その関数からの応答を取得してデバイスに返します。

この目的のために、私はREST Slim frameworkを使用したAPIを開発しました。

しかし、私が現在直面している主要なブロッカーは、PHPFox Webサイトのリソース(関数やデータ)へのアクセスです。

Webサイトのリソースにアクセスするために'Token Based Authentication'を使用してユーザーを認証する方法を理解していません。

誰かが役に立つ実用的な例を使って適切な方向に私を導くことができれば、それは私にとって本当に役立つでしょう。

N.B. :提案された「トークンベースの認証」の実装は、非常に安全で高速でなければなりません。セキュリティは決して損なわれるべきではありません。

以下は自分で試したコードですが、正しいか間違っているかはわかりません。私のアプローチは正しいか間違っていますか。誰かがそれを分析し、それに関するあなたのフィードバックを教えてください。

トークンを作成するには、パラメーターとしてユーザーのデータを取得するこの関数を使用します

define('SECRET_KEY', "fakesecretkey");

function createToken($data)
{
    /* Create a part of token using secretKey and other stuff */
    $tokenGeneric = SECRET_KEY.$_SERVER["SERVER_NAME"]; // It can be 'stronger' of course

    /* Encoding token */
    $token = hash('sha256', $tokenGeneric.$data);

    return array('token' => $token, 'userData' => $data);
}

したがって、ユーザーは自分自身を認証し、トークン(genericPart +彼のデータ、エンコード済み)、およびエンコードされていないhisDataを含む配列を受け取ることができます。

function auth($login, $password)
{
    // we check user. For instance, it's ok, and we get his ID and his role.
    $userID = 1;
    $userRole = "admin";

    // Concatenating data with TIME
    $data = time()."_".$userID."-".$userRole;
    $token = createToken($data);
    echo json_encode($token);
}

次に、ユーザーはトークンとエンコードされていないデータを送信して確認することができます:

define('VALIDITY_TIME', 3600);

function checkToken($receivedToken, $receivedData)
{
    /* Recreate the generic part of token using secretKey and other stuff */
    $tokenGeneric = SECRET_KEY.$_SERVER["SERVER_NAME"];

    // We create a token which should match
    $token = hash('sha256', $tokenGeneric.$receivedData);   

    // We check if token is ok !
    if ($receivedToken != $token)
    {
        echo 'wrong Token !';
        return false;
    }

    list($tokenDate, $userData) = explode("_", $receivedData);
    // here we compare tokenDate with current time using VALIDITY_TIME to check if the token is expired
    // if token expired we return false

    // otherwise it's ok and we return a new token
    return createToken(time()."#".$userData);   
}

$check = checkToken($_GET['token'], $_GET['data']);
if ($check !== false)
    echo json_encode(array("secureData" => "Oo")); // And we add the new token for the next request

私は正しいですか?

ありがとう。

24
PHPFan

まず、トークンベースの認証とは何かを理解する必要があります。以下のように説明できます。

トークンベースの認証システムの背後にある一般的な概念は単純です。ユーザーが特定のリソースを取得できるトークンを取得するために、ユーザー名とパスワードを入力できるようにします-ユーザー名とパスワードを使用しません。トークンを取得すると、ユーザーはトークンを提供できます。トークンは、特定のリソースへのアクセスを一定期間提供しますが、リモートサイトに提供します。

続きを読む

それでは、REST Webサービスで実装する手順を見てみましょう。

次の制御フローを使用します。

  • ユーザーはログインフォームでユーザー名とパスワードを入力し、[ログイン]をクリックします。
  • 要求が行われた後、データベースでクエリを実行して、バックエンドでユーザーを検証します。リクエストが有効な場合、データベースから取得したユーザー情報を使用してトークンを作成し、その情報を応答ヘッダーで返します。これにより、トークンブラウザをローカルストレージに保存できます。
  • アプリケーションの制限されたエンドポイントにアクセスするために、すべてのリクエストヘッダーにトークン情報を提供します。
  • 要求ヘッダー情報からフェッチされたトークンが有効な場合、指定されたエンドポイントにユーザーがアクセスできるようにし、JSONまたはXMLで応答します。

制御の流れについては、以下の画像を参照してください

enter image description here

JWTとは何か疑問に思われるかもしれません

JWTはJSON Web Tokenの略で、認証ヘッダーで使用されるトークン形式です。このトークンは、2つのシステム間の通信を安全な方法で設計するのに役立ちます。このチュートリアルの目的のために、JWTを「ベアラートークン」と言い換えてみましょう。ベアラートークンは、ヘッダー、ペイロード、および署名の3つの部分で構成されます。

  • ヘッダーは、トークンタイプと暗号化方式を保持するトークンの一部であり、base64でエンコードされます。
  • ペイロードには情報が含まれます。ユーザー情報、製品情報など、あらゆる種類のデータを配置できます。これらはすべてbase64エンコードで保存されます。
  • 署名は、ヘッダー、ペイロード、および秘密鍵の組み合わせで構成されます。秘密鍵はサーバー側で安全に保管する必要があります。 JWTスキーマとトークンの例を以下に示します。

enter image description here

php-jwt を使用できるため、ベアラートークンジェネレーターを実装する必要はありません。

上記があなたの混乱を説明することを望みます。トークンベースの認証を実装する際に問題が発生した場合はお知らせください。お手伝いしましょう。

77
Techie