2016-09-07 6 views
1

セッショントークンでフォームを保護するためのスクリプトを作成しました。私のスクリプトは、トークンをチェックする前にフォームフィールドを検証しようとすると動作しません。誰かが私のスクリプトで何が間違っているのか理解してくれますか?セッショントークンでフォームを保護する

<?php 
      session_start(); 
      class TOKEN { 
      public static function generate() { 
       return $_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(15)); 
      } 
      public static function check($token) { 
       if (isset($_SESSION['token']) && $token === $_SESSION['token']) { 
       unset($_SESSION['token']); 
       return true; 
       } 
       return false; 
      } 
      } 
     ?> 
     <?php 
      $display_form = FALSE; 
      if (isset($_POST['submit'])) { 
      $username = $_POST['username']; 
      $userpass = $_POST['userpass']; 

      if (strlen($username) < 4) { 
       $error_name = 'required'; 
       $display_form = true; 
       $validation_error = true; 
      } 
      if (strlen($userpass) < 8) { 
       $error_pass = 'required'; 
       $display_form = true; 
       $validation_error = true; 
      } 
      if (!$validation_error) { 
       if (TOKEN::check($_POST['token'])) { 
       echo 'process form'; 
       } else { 
       echo 'invalid security token'; 
       } 
      } 
      } else { 
      $display_form = TRUE; 
      } 
     ?> 
     <!DOCTYPE html> 
     <html lang="en"> 
     <head> 
      <meta charset="UTF-8"> 
      <title>Title</title> 
     </head> 
     <body> 
     <?php 
      if ($display_form == true) { 
     ?> 
     <form method="post" action="<?php echo htmlspecialchars($_SERVER['REQUEST_URI']); ?>"> 
      <input type="hidden" name="token" value="<?php echo TOKEN::generate(); ?>"> 
      <input type="text" name="username" id="" placeholder="username"> 
      <?php echo $error_name; ?> 
      <br> 
      <input type="password" name="userpass" id="" placeholder="Password"> 
      <?php echo $error_pass; ?> 
      <br> 
      <input type="submit" name="submit" value="Sign in"> 
     </form> 
     </body> 
     </html> 
     <?php 
     } 
     ?> 
+0

あなたが生成されたHTMLを確認しましたか? '$ _POST'をチェックしましたか? –

+0

はい、私はして、トークンは、HTMLで生成されます。私がエラーなしでフォームを提出すれば、それは動作します。しかし、いずれかまたは両方のフィールドが必要な場合、フィールドの検証を修正してからフォームを送信すると、無効なセキュリティトークンが表示されます。 – Bootflux

答えて

0

このコードは非常に読みにくいです。ステートメントの開始と終了のタイミングはわかりません。また、すべてのクラスの使用を停止します。大きな男の子のような手続き型プログラミングを使う。

あなたの問題は単純なものです。 $validation_errorは外部スコープで初期化されませんでした。それが文章の間に救われなかったという意味。私はここでの問題は、次のようになっていることを想定

... 
$display_form = FALSE; 
$validation_error = false; // right here 
      if (isset($_POST['submit'])) { 
      $username = $_POST['username']; 
      $userpass = $_POST['userpass']; 
      ... 
0

:これは単に外側のスコープで$validation_error = falseを追加する修正するには

  1. あなたはでトークンを持っているとセッション内のトークン。彼らは平等です。
  2. フォームにエラーを入力すると、フォームが再度読み込まれます。しかし! セッションにはポイント1の以前のトークンがあり、フォームには新しいトークンがあります。
  3. もう一度送信し、別のトークンをチェックします。

ので、解決策は常に、フォームで間違っているか、正しい値を持っているどんなにunsetトークンにあります。

更新:

私はそれのようなものであるべきとします

if (!$validation_error) { 
    // here token will be removed in `TOKEN::check` 
    if (TOKEN::check($_POST['token'])) { 
    echo 'process form'; 
    } else { 
    echo 'invalid security token'; 
    } 
} else { 
    // remove token implicitly 
    TOKEN::remove(); 
} 

そしてTOKEN中:

public static function check($token) { 
    $result = false; 

    if (isset($_SESSION['token'])) { 
    if ($token === $_SESSION['token']) { 
     $result = true; 
    } 
    // if token set - remove it 
    self::remove(); 
    } 

    return $result; 
} 

public static function remove() { 
    unset($_SESSION['token']); 
} 
+0

u_mulder、あなたは絶対に正しいです、これが起こっています、あなたは私に未設定のトークンを含める必要があると教えてください?それは私がすべきことです:unset($)SESSION ['token']); – Bootflux

+0

更新された回答を確認してください。 –

+0

上記のソリューションを適用した後に無効なセキュリティトークンが取得される – Bootflux

関連する問題