web-dev-qa-db-ja.com

Laravel:ランダムな一意のトークンを生成する

私のデータベースには、次の構造を持つkeysというテーブルがあります。

id | user_id | token_id | token_key

ユーザーがサイトにログインするたびに、そのユーザー用に新しいtoken_idおよびtoken_keyセットを生成する必要があります。 2つの値を一意に保ちながら、token_idtoken_keyの両方に対してランダムトークンを生成するにはどうすればよいですか?

たとえば、次の場合:

  • token_iddfbs98641aretwsgです、
  • token_keysdf389dxbf1sdz51fga65dfg74asdfです

意味:

id | user_id | token_id         | token_key
1  | 1       | dfbs98641aretwsg | sdf389dxbf1sdz51fga65dfg74asdf

そのトークンの組み合わせを持つテーブルには、他の行は存在できません。これどうやってするの?

9
user5486944

このようなケースに余分なパッケージを含めることは避けたいです。何かのようなもの:

do {
    $token_id = makeRandomToken();
    $token_key = makeRandomTokenKey();
} while (User::where("token_id", "=", $token_id)->where("token_key", "=", $token_key)->first() instanceof User);

...すべきです。 「ユーザー」と異なる場合は、モデル名を自分のものに置き換え、ランダム文字列を作成するためにユーザーまたは提案された関数を使用します。

15

トークンの生成に関しては、 Laravelのヘルパー関数 ;のいずれかを使用できます。 str_random()

これにより、指定された長さのランダムな文字列が生成されます。たとえば、str_random(16)は16文字のランダムな文字列(大文字、小文字、数字)を生成します。

トークンの使用方法に応じて、トークンは本当に完全に一意である必要がありますか?それらがユーザーに一致する場合、または_token_id_を使用し、_token_key_に対してこれを検証している可能性があると仮定すると、それらのいずれかが2つある場合は本当に重要ですか? -これの可能性は非常に小さいですが!

ただし、本当に一意である必要がある場合は、unique制約付きのバリデーターをいつでも使用できます。 このパッケージ を使用すると、_unique_with_を使用して、これら2つが一意であることもテストできます。そして、バリデーターが失敗すると、必要に応じて新しいトークンを生成します。

例に基づいて、str_random(16)を_token_id_に、str_random(30)を_token_key_に使用します。

20
James

@ivanhoeの提案に続いて...これは私が思いついたものです:-

    $token = new Token;

    //in case there are duplicate
    for ($x = 0; $x < 10; $x ++) {
        $token->access_token = str_random(16);;
        try {
            if ($token->save()) {
                break;
            }
        }catch (QueryException $e) {

        }
    }
1
daisura99

これを行うには、依存関係を使用できます。 Dirape laravel-token

コマンドを実行する

composer require dirape/token

コントローラーで使用

use Dirape\Token\Token;

次のように使用できます。

User::create([
        'name'             => $data['name'],
        'email'            => $data['email'],
        'password'         => bcrypt($data['password']),
        'token_key' => (new Token())->Unique('users', 'api_token', 60),
        'active'           => 1
    ])