LoginSignup
84
64

More than 3 years have passed since last update.

PHPの標準関数を使ってユニーク(一意)なトークン(文字列)を生成する

Last updated at Posted at 2019-05-22

PHPの標準関数のみでユニークなトークンを作りたかったので、メモとして残します。

目的

メールアドレス認証時に使用するアクティベーションキー用のトークンを発行したく、
実行する度に被らないランダムな文字列を取得するのが目的です。

TL;DR

uniqid(bin2hex(random_bytes(1)))

環境

PHP7系

乱数に使えそうな関数を探す

uniqid

uniqid ([ string $prefix = "" [, bool $more_entropy = FALSE ]] ) : string

マイクロ秒単位の現在時刻にもとづいた、接頭辞つきの一意な ID を取得します。
この関数は、戻り値の一意性を保証するものではありません。

uniqid() // 5ce3d9f085632
uniqid() // 5ce3d9f154c7a
uniqid() // 5ce3d9f25823a

13桁の16進数の文字列が返ってくるようです。
現在時刻に基づいてるので実行するたびにカウントアップされていくようです。

uniqid には第一引数で接頭辞を付けられます。

uniqid('ucan-') // ucan-5ce3dabb38549
uniqid('ucan-') // ucan-5ce3dabbe1c38
uniqid('ucan-') // ucan-5ce3dabc5407c

接頭辞を付けられるのは便利だったのですが、
固定文字列を付けてしまうと結局一意性は保証されません。

dechex

10 進数を 16 進数に変換する

dechex ( int $number ) : string

$number で指定した符号なし整数値を 16 進数表現した文字列を返します。

dechex(0) // 0
dechex(100) // 64
dechex(255) // ff

random_int

暗号学的に安全な疑似乱数整数を生成する。

random_int ( int $min , int $max ) : int

$min$max の間で偏りのない結果が重要な場合に使用するのに適した暗号化された乱数整数を生成します。

random_int(0, 255) // 4
random_int(0, 255) // 158
random_int(0, 255) // 184

乱数を生成する

16進数2桁(0 〜 ff)の乱数を生成して接頭辞を付ける。

uniqid(dechex(random_int(0, 255))) // 865ce3dddb0e35b
uniqid(dechex(random_int(0, 255))) // 85ce3dddb13e1d
uniqid(dechex(random_int(0, 255))) // b25ce3dddb198dc

乱数を生成する(固定桁数)

もし桁数を固定したい場合は sprintf を使って0埋めすると良さそうかな🤔

uniqid(sprintf('%02x', random_int(0, 255))) // 4e5ce3dd8d7e2de
uniqid(sprintf('%02x', random_int(0, 255))) // 0a5ce3dd8d83477
uniqid(sprintf('%02x', random_int(0, 255))) // 4f5ce3dd8d8925d

2019.05.23 追記

@suin さんから random_bytes もオススメのコメントいただきました!

random-bytes

random_bytes - 暗号学的に安全な疑似乱数バイトを生成する

random_bytes ( int $length ) : string

salt、鍵、または初期化ベクトルを生成するときなど、暗号用途に適した任意の長さの暗号ランダムバイトの文字列を生成します。

random_bytes(1) とすると1byteのバイナリ文字列が返ります。
バイナリ文字列から16進数に bin2hex 関数で変換すれば 00ff を取得できます。

uniqid(bin2hex(random_bytes(1))) // 085ce642e0803c3
uniqid(bin2hex(random_bytes(1))) // 555ce642e2cb9fa
uniqid(bin2hex(random_bytes(1))) // eb5ce642e463215

2019.05.24 追記

@go12lim さんから uniqid の第二引数使うとシンプルに書けるとアドバイスいただきました🙇‍♂️

uniqid('', true) // "5ce7b766c4b586.26307700"
uniqid('', true) // "5ce7b767d85ab4.09025400"
uniqid('', true) // "5ce7b7687dd943.84230183"

これが一番シンプルで良さそうです!
ドット付きが気にならなければこれで良さそう!

参考

関連記事

84
64
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
84
64