2013-10-21 45 views
1

我爲我的網站創建了一個Ajax登錄,但我覺得我可以優化它,但我不知道如何以及在哪裏。如何優化我的登錄腳本?

問題:

  • 如何優化我的代碼?
  • 代碼是否安全?任何方式來打破它(注射等)?

此外,當我嘗試登錄時,它目前需要大約1秒來處理登錄(在本地主機上)。這很長嗎?

這裏是我的Ajax調用:

$(document).ready(function() { 
    $(document).on("submit", "form", function(event) { 
    event.preventDefault(); 
    $.ajax({ 
     url: 'assets/php/login_script.php', 
     type: 'POST', 
     data: $(this).serialize(), 
     success: function(data) { 
     if (data == true) { 
      window.location.href = "index.php"; 
     } else { 
      $("input[name=password_field]").focus(); 
      $(".error").html(data); 
     } 
     } 
    }); 
    }); 
}); 

這裏的PHP腳本:

<?php 

    include_once("access.php"); 

    $cxn = mysqli_connect($host, $user, $pass, $db) or die ("Couldn't connect to the server. Please try again."); 

    $username = $_POST["username"]; 
    $password = $_POST["password"]; 
    $date = date('Y-m-d h:i:s', time()); 
    $ip_address = get_ip_address(); 
    $expire = time() + 86400 * 365; 

    $options = array('cost' => 12); 
    $hash_password = password_hash($password, PASSWORD_BCRYPT, $options); 

    /* Log the login request. */ 
    $stmt = $cxn->prepare("INSERT INTO login_logs (log_id, username, password, datetime, ip_address) VALUES ('', ?, ?, ?, ?)"); 
    $stmt->bind_param('ssss', $username, $hash_password, $date, $ip_address); 
    $stmt->execute(); 

    /* Get user information from database. */ 
    $stmt = $cxn->prepare('SELECT * FROM users WHERE username = ?'); 
    $stmt->bind_param('s', $username); 
    $stmt->execute(); 
    $result = $stmt->get_result(); 

    /* If a result exists, continue. */ 
    if ($result->num_rows > 0) { 
    while ($row = $result->fetch_assoc()) { 
     $db_username = $row['username']; 
     $db_password = $row['password']; 
     $random_hash = password_hash(time() . $db_username . time(), PASSWORD_BCRYPT, $options); 

     /* Password matches. */ 
     if (password_verify($password, $db_password)) { 

     /* Get user's cookie information in database. */ 
     $stmt2 = $cxn->prepare("SELECT * FROM cookies WHERE username = ?"); 
     $stmt2->bind_param('s', $db_username); 
     $stmt2->execute(); 
     $result2 = $stmt2->get_result(); 

     /* If a result exists, update the cookie. */ 
     if ($result2->num_rows > 0) { 
      $stmt = $cxn->prepare("UPDATE cookies SET hash = ? WHERE username = ?"); 
      $stmt->bind_param('ss', $random_hash, $db_username); 
      $stmt->execute(); 

      setcookie("user", $db_username, $expire, "/"); 
      setcookie("hash", $random_hash, $expire, "/"); 
     } else { 
      $stmt = $cxn->prepare("INSERT INTO cookies (cookie_id, username, hash) VALUES ('', ?, ?)"); 
      $stmt->bind_param('ss', $db_username, $random_hash); 
      $stmt->execute(); 

      setcookie("user", $db_username, $expire, "/"); 
      setcookie("hash", $random_hash, $expire, "/"); 
     } 

     echo true; 
     } else { 
     echo "Incorrect credentials."; 
     } 
    } 
    } else { 
    echo "Incorrect credentials."; 
    } 

    function get_ip_address() { 
    $ip_address = ''; 
    if (getenv('HTTP_CLIENT_IP')) 
     $ip_address = getenv('HTTP_CLIENT_IP'); 
    else if(getenv('HTTP_X_FORWARDED_FOR')) 
     $ip_address = getenv('HTTP_X_FORWARDED_FOR'); 
    else if(getenv('HTTP_X_FORWARDED')) 
     $ip_address = getenv('HTTP_X_FORWARDED'); 
    else if(getenv('HTTP_FORWARDED_FOR')) 
     $ip_address = getenv('HTTP_FORWARDED_FOR'); 
    else if(getenv('HTTP_FORWARDED')) 
     $ip_address = getenv('HTTP_FORWARDED'); 
    else if(getenv('REMOTE_ADDR')) 
     $ip_address = getenv('REMOTE_ADDR'); 
    else 
     $ip_address = 'UNKNOWN'; 

    return $ip_address; 
    } 

?> 

如何優化我的腳本看起來更好,更快,等等?

+0

應該在codereview上提問,這裏不是 – 2013-10-21 22:08:24

回答

2

延遲一秒鐘的問題是連接到localhost,這是PDO的問題。只需將localhost更改爲127.0.0.1即可解決延遲問題。

代碼的其餘部分看起來不錯,乾淨,我很好,工作。 :)

+1

啊,謝謝你把它改成'127.0.0.1'。 :) – Burrows

+0

哈哈是的,我有同樣的問題多年。順便說一句,如果你想知道,它與DNS有關。當連接到'localhost'時,PDO不斷嘗試刷新DNS內容,這就是爲什麼你應該使用IP地址。簡單但有效的解決方案 –

+0

啊好的。感謝您的額外信息。 :) – Burrows

1

看起來總體上不錯。乍一看事情夫婦:

你大於0的if語句是多餘的:

if ($result->num_rows) { 
if ($result2->num_rows) { 

人們會認爲你的用戶名是獨一無二的。因此,你不應該循環結果。

假設您的_id字段是自動增量主鍵字段,您不需要在查詢中指定它們。即將它們從字段和值列表中刪除。

檢查您使用的IP地址。您在此處使用它來確保登錄安全性,但是您從一系列用戶提供的標題中獲取它。我建議,除非有充分的理由才能獲得'真正的'IP,否則應該只使用REMOTE_ADDR。

您可以通過使用INSERT INTO ... ON DUPLICATE KEY UPDATE來刪除「SELECT cookie,我選擇了什麼?UPDATE或INSERT」邏輯......有關語法的信息,請參閱INSERT上的MySQL手冊。

您正在使用cookie來存儲用戶名/散列。考慮一下你是否真的需要這樣做,因爲它增加了你必須檢查cookie中的用戶名是什麼邏輯,每次需要時它應該是什麼的複雜性。如果你可以避開使用$ _SESSION,我會建議這樣做。