1

SQLインジェクションを回避するために、プリペアドステートメントを使用してPHPスクリプトを作成しようとしました。また、3つのphpファイルを作成しました。

  1. db_connect.php(ここには、データベースに接続するためのすべての情報が格納されています)

  2. functions.php(セッションの作成、ログイン試行のチェック、および機能-loginおそらく間違いを犯したが見つからない場合)

  3. process_login.php(上記の2つのファイルのセット。POST変数がこのページに送信されない場合はlogin_success、エラーページにリダイレクトするか、無効な要求を出力します)。

さらに、値を挿入しようとするたびに無効なリクエストfunctions.phpが表示されるため、おそらく間違いです。フィールドが空であるか、データベースユーザーからの値が含まれているかは関係ありません。

<?php


function sec_session_start() {
    $session_name = 'sec_session_id'; // Set a custom session name
    $secure = false; // Set to true if using https.
    $httponly = true; // This stops javascript being able to access the session id.

    ini_set('session.use_only_cookies', 1); // Forces sessions to only use cookies.
    $cookieParams = session_get_cookie_params(); // Gets current cookies params.
    session_set_cookie_params($cookieParams["lifetime"], $cookieParams["path"], $cookieParams["domain"], $secure, $httponly);
    session_name($session_name); // Sets the session name to the one set above.
    session_start(); // Start the php session
    session_regenerate_id(true); // regenerated the session, delete the old one.   
}

function login($postcode, $ref, $mysqli) {
  // Using prepared Statements means that SQL injection is not possible.
 if ($stmt = $mysqli->prepare("SELECT ref_no, postcode FROM customers WHERE ref_no = ?           LIMIT 1")) {
  $stmt->bind_param('ss', $postcode,$ref); // Bind "$email" to parameter.
  $stmt->execute(); // Execute the prepared query.
  $stmt->bind_result($dbref,$dbpostcode); // get variables from result.
    // $stmt->fetch();
  $a = array();
while ($stmt->fetch()) {
$a = array('ref' => $dbref , 'postcode' => $dbpostcode);
}

  if ($_POST['ref']==$dbref && $_POST['postcode']==$dbpostcode){ // If the user exists
    // We check if the account is locked from too many login attempts
    if(checkbrute($ref, $mysqli) == true) {
        // Account is locked

        return false;
    } else {
    if($dbref == $ref) { // Check if the password in the database matches the password the user submitted.
        // Password is correct!

          $ip_address = $_SERVER['REMOTE_ADDR']; // Get the IP address of the user.
          $user_browser = $_SERVER['HTTP_USER_AGENT']; // Get the user-agent string of the user.

          if(preg_match("/^[0-9a-zA-Z]{5,7}$/", $_POST["postcode"]) === 0)
'<p class="errText">Please enter valid postcode!</p>';
          else{ $_SESSION['postcode'] = $postcode;}
          if(preg_match("/^[0-9]{4,6}$/", $_POST["ref"]) === 0) '<p      class="errText">Please enter valid reference number ! </p>';
          else{
          $_SESSION['ref'] = $ref;}
                        // Login successful.
          return true;   
    } else {
        // Password is not correct
        // We record this attempt in the database
        $now = time();
        $mysqli->query("INSERT INTO login_attempts (ref_no, time) VALUES ('$ref', '$now')");
        return false;
    }
  }
  } else {
    // No user exists.
    return false;
  }
  }
   }

function checkbrute($ref, $mysqli) {
  // Get timestamp of current time
  $now = time();
  // All login attempts are counted from the past 2 hours.
  $valid_attempts = $now - (2 * 60 * 60);

  if ($stmt = $mysqli->prepare("SELECT time FROM login_attempts WHERE ref_no = ? AND    time > '$valid_attempts'")) {
  $stmt->bind_param('i', $ref);
  // Execute the prepared query.
  $stmt->execute();
  $stmt->store_result();
  // If there has been more than 3 failed logins
  if($stmt->num_rows > 3) {
    return true;
  } else {
    return false;
  }
   }
}

?>

そして、これはprocess_login.phpユーザー検証が失敗する場所です。

<?php
include 'db_connect.php';
include 'functions.php';


sec_session_start(); //

if(isset($_POST['postcode'], $_POST['ref'])) {

  if(login($postcode, $ref, $mysqli) == true) {
  // Login success
  echo 'Success: You have been logged in!';
 } else {
  // Login failed
  header('Location: ./login.php?error=1');
  }
} else {
  // The correct POST variables were not sent to this page.
  echo 'Invalid Request';
}

?>

どんな助けでも大歓迎です。ありがとう。

4

2 に答える 2

1

バインドする$変数は1つだけです。2つをバインドしようとしています:

if ($stmt = $mysqli->prepare("SELECT ref_no, postcode FROM customers WHERE ref_no = ?           LIMIT 1")) {
  $stmt->bind_param('ss', $postcode,$ref); // Bind "$email" to parameter.

唯一 ?および2つのbind_param......

する必要があります:

if ($stmt = $mysqli->prepare("SELECT ref_no, postcode FROM customers WHERE ref_no = ?           LIMIT 1")) {
  $stmt->bind_param('s', $ref); // Bind "$email" to parameter.

私はこれをテストしていませんが、ログイン機能に必要なものは次のとおりです。

function login($postcode, $ref, $mysqli)
{
// Using prepared Statements means that SQL injection is not possible.
if ($stmt = $mysqli->prepare("SELECT ref_no, postcode FROM customers WHERE ref_no = ? LIMIT 1"))
    {
        $stmt->bind_param('s',$ref); // Bind "$email" to parameter.
        $stmt->execute(); // Execute the prepared query.
        $stmt->store_result();
        $stmt->bind_result($dbref,$dbpostcode); // get variables from result.
    while ($stmt->fetch())
        {
        if($stmt->num_rows > 0)
            {
            $now = time();
            if ($_POST['ref'] == $dbref && $_POST['postcode'] == $dbpostcode)
                {// If the user exists
                    if(checkbrute($ref, $mysqli) == true)
                        {                               
                            $mysqli->query("INSERT INTO login_attempts (ref_no, time) VALUES ('".$dbref."', '".$now."')");
                            return false;
                        }
                    $ip_address = $_SERVER['REMOTE_ADDR']; // Get the IP address of the user.
                    $user_browser = $_SERVER['HTTP_USER_AGENT']; // Get the user-agent string of the user.
                    if(!preg_match("/^[0-9a-zA-Z]{5,7}$/", $_POST["postcode"]))
                        {
                            $mysqli->query("INSERT INTO login_attempts (ref_no, time) VALUES ('".$dbref."', '".$now."')");
                            $error = '<p class="errText">Please enter valid postcode!</p>';
                            return $error;
                        }
                    $_SESSION['postcode'] = $postcode;
                    if(!preg_match("/^[0-9]{4,6}$/", $_POST["ref"]))
                        {
                            $mysqli->query("INSERT INTO login_attempts (ref_no, time) VALUES ('".$dbref."', '".$now."')");
                            $error = '<p class="errText">Please enter valid reference number ! </p>';
                            return $error;
                        }
                    $_SESSION['ref'] = $ref;
            return true;
            }
        //no rows returned
        $mysqli->query("INSERT INTO login_attempts (ref_no, time) VALUES ('".$dbref."', '".$now."')");
        return false;       
        }
    //no statement fetched
    return false;
    }
//no statment prepared
return false;
}

これをコードに追加し直しましたが、その使用法がわかりません。このスコープでは返されたり使用されたりしません:

$ip_address = $_SERVER['REMOTE_ADDR']; // Get the IP address of the user.
$user_browser = $_SERVER['HTTP_USER_AGENT']; // Get the user-agent string of the user.
于 2013-01-16T23:59:43.383 に答える
1

それを試してみてください :

if ($stmt = $mysqli->prepare("SELECT ref_no, postcode FROM customers WHERE ref_no = ?           LIMIT 1")) {
  $stmt->bind_param('%s%s', $postcode,$ref); // Bind "$email" to parameter.
于 2013-01-17T01:03:48.683 に答える