LoginSignup
0
0

使用済みのワンタイムパスワードを再利用できないようにするには、データベースやキャッシュに保存する方法が一般的です。以下に、PHPでデータベースとキャッシュを利用した具体的な対策例を紹介します。

データベースを利用する場合

  1. データベースにテーブルを作成し、以下のカラムを定義します。

    • user_id: ユーザーID
    • otp: ワンタイムパスワード
    • timestamp: ワンタイムパスワードの生成時刻
  2. ワンタイムパスワードを生成したら、データベースにレコードを挿入します。

<?php

$userId = 1; // ユーザーID
$otp = generateOTP(); // ワンタイムパスワードを生成
$timestamp = time(); // 現在時刻を取得

$db = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$stmt = $db->prepare('INSERT INTO otps (user_id, otp, timestamp) VALUES (:user_id, :otp, :timestamp)');
$stmt->bindParam(':user_id', $userId);
$stmt->bindParam(':otp', $otp);
$stmt->bindParam(':timestamp', $timestamp);
$stmt->execute();

?>
  1. ワンタイムパスワードを検証する前に、データベースにレコードが存在するか確認します。
<?php

$userId = 1; // ユーザーID
$otp = '123456'; // 入力されたワンタイムパスワード
$timestamp = time(); // 現在時刻を取得

$db = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$stmt = $db->prepare('SELECT * FROM otps WHERE user_id = :user_id AND otp = :otp AND timestamp >= :timestamp - 30'); // 過去30秒以内に生成されたワンタイムパスワードのみ検証
$stmt->bindParam(':user_id', $userId);
$stmt->bindParam(':otp', $otp);
$stmt->bindParam(':timestamp', $timestamp);
$stmt->execute();

$result = $stmt->fetchAll();

if (count($result) > 0) {
  // ワンタイムパスワードが有効
  echo 'Valid OTP';

  // 使用済みのワンタイムパスワードを削除
  $stmt = $db->prepare('DELETE FROM otps WHERE user_id = :user_id AND otp = :otp');
  $stmt->bindParam(':user_id', $userId);
  $stmt->bindParam(':otp', $otp);
  $stmt->execute();
} else {
  // ワンタイムパスワードが無効
  echo 'Invalid OTP';
}

?>

キャッシュを利用する場合

  1. Memcached や Redis などのキャッシュサーバーをインストールします。

  2. ワンタイムパスワードを生成したら、キャッシュに保存します。

<?php

$userId = 1; // ユーザーID
$otp = generateOTP(); // ワンタイムパスワードを生成
$timestamp = time(); // 現在時刻を取得

$memcached = new Memcached();
$memcached->addServer('localhost', 11211);
$memcached->set($userId . ':' . $otp, $timestamp, 30); // 30秒間キャッシュする

?>
  1. ワンタイムパスワードを検証する前に、キャッシュにレコードが存在するか確認します。
<?php

$userId = 1; // ユーザーID
$otp = '123456'; // 入力されたワンタイムパスワード
$timestamp = time(); // 現在時刻を取得

$memcached = new Memcached();
$memcached->addServer('localhost', 11211);
$cachedTimestamp = $memcached->get($userId . ':' . $otp);

if ($cachedTimestamp !== false && $cachedTimestamp >= $timestamp - 30) {
  // ワンタイムパスワードが有効
  echo 'Valid OTP';

  // キャッシュからレコードを削除
  $memcached->delete($userId . ':' . $otp);
} else {
  // ワンタイムパスワードが無効
  echo 'Invalid OTP';
}

?>

その他の対策

  • ワンタイムパスワードの長さを十分に長くする (少なくとも 6 桁)
  • ワンタイムパスワードの有効期限を短くする (30 秒など)
  • ワンタイムパスワードを複数回入力できないようにする (例えば、入力画面に残り試行回数カウンターを表示する)

これらの対策を組み合わせることで、より安全な二段階認証システムを構築することができます。

0
0
0

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
0
0