2013-01-16 169 views
1

我試圖用準備好的語句來製作PHP腳本以避免SQL注入。另外我創建了3個php文件。通過PHP驗證用戶

  1. db_connect.php(這裏存儲所有信息,用於連接到數據庫)

  2. functions.php(創建會議,檢查登錄嘗試,和功能login -where我可能犯了一個錯誤,但不能找到它)

  3. process_login.php(一組兩個文件的上方,還重定向到login_success,錯誤頁面,或者打印無效的請求如果沒有POST變量發送到此頁面)。

在增補爲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'; 
} 

?> 

任何幫助將是最受歡迎的。謝謝。

+0

在'process_login.php'的var_dump()你的$ _ POST右下方'sec_session_start();',看看如果有什麼實際上是張貼。 'var_dump($ _ POST);' – kylex

+0

表單輸入名稱屬性的命名是否正確? –

+0

謝謝你們的快速解答。我已經嘗試var_dump($ _ POST),就像kylex說的,我得到:** array(0){}無效的請求** – user1981437

回答

1

您只有一個$變量進行綁定。您正試圖綁定兩個:

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. 

只有一個?和兩個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. 
+0

感謝您的回答羅伊,我已經嘗試過,但仍然是:/ – user1981437

+0

@ user1981437 I編輯我的答案以顯示您的登錄功能的返工。任何時候你使用'return',正確地完成你可以忽略'else'。我沒有測試過,所以試試看。 –

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. 
+2

謝謝Mostafa,我改變了我的代碼,但仍然得到同樣的錯誤。 – user1981437

+1

+1謝謝。祝你好運。 – shgnInc