2014-12-13 48 views
1

基本上,我希望我的代碼能夠從SQL注入安全。我在網上閱讀,mysqli_real_escape_string是不安全的SQL注入和閱讀參數化的路要走。因此,從下面的代碼中,我可以將帳戶添加到數據庫中,但我無法檢查帳戶是否已經存在。嘗試參數化SELECT查詢

<?php 
require 'privstuff/dbinfo.php'; 

$firstname = $_POST["firstname"]; 
$password1 = $_POST["password1"]; 
$email = $_POST["email"]; 
$ip = $_SERVER['REMOTE_ADDR']; 
$username = $_POST["username"]; 

$mysqli = new mysqli(DB_SERVER, DB_USER, DB_PASSWORD, DB_DATABASE); 


if(mysqli_connect_errno()) { 
    echo "Connection Failed. Please send an email to [email protected] regarding this problem."; 
    exit(); 
} 


//$username = mysqli_real_escape_string($mysqli,$_POST['username']);  
//$result = mysqli_query($mysqli,"SELECT `username` FROM `accounts` WHERE username = '$username'"); 



if ($stmt = $mysqli->prepare("SELECT `username` FROM `accounts` WHERE username = ?")) { 


    $stmt -> bind_param("s", $username); 

    $stmt -> execute(); 

    $stmt -> bind_result($result); 

    $stmt -> fetch(); 

    $stmt -> close(); 
} 

if(mysqli_num_rows($result)>0){ 

    header('Location: /register.html'); 
}else{ 
    if ($stmt = $mysqli->prepare("INSERT INTO `accounts`(`firstname`, `username`, `password`, `email`, `ip`) VALUES (?,?,?,?,?)")) { 


     $stmt -> bind_param("sssss", $firstname, $username, password_hash($password1, PASSWORD_BCRYPT), $email, $ip); 

     $stmt -> execute(); 

     $stmt -> bind_result($result); 

     $stmt -> fetch(); 

     $stmt -> close(); 
    } 


    $mysqli->close(); 
    header('Location: /login.html'); 
} 

?> 

由於問題是擱置,我不能添加我自己的答案。 Reddit上的某人對這個問題給出了一個很好的解釋。 Here it is

回答

1

一個參數化的好處是,你不再需要直接關心自己與handling of quotes各種數據類型 - 它們將被綁定處理:

$mysqli->prepare("SELECT `username` FROM `accounts` WHERE username = ?" ... 
1

除了@斯圖亞特答案上面覆蓋在準備好的聲明,你引用的num_rows放錯了地方的報價:

$stmt -> bind_result($result); 
if(mysqli_num_rows($result)>0){ 

你應該是它引用到狀態換貨對象:

if($stmt->num_rows > 0) { 
    // do whats necessary  
} 

和插入後取行沒有意義,你實際上並不需要這些。

下面是它的一個編譯:

<?php 
require 'privstuff/dbinfo.php'; 

$firstname = $_POST["firstname"]; 
$password1 = $_POST["password1"]; 
$email = $_POST["email"]; 
$ip = $_SERVER['REMOTE_ADDR']; 
$username = $_POST["username"]; 

$mysqli = new mysqli(DB_SERVER, DB_USER, DB_PASSWORD, DB_DATABASE); 
if(mysqli_connect_errno()) { 
    echo "Connection Failed. Please send an email to [email protected] regarding this problem."; 
    exit; 
} 

if ($stmt = $mysqli->prepare("SELECT `username` FROM `accounts` WHERE username = ?")) { 
    $stmt->bind_param("s", $username); 
    $stmt->execute(); 
} 

if($stmt->num_rows > 0) { 
    header('Location: /register.html'); 
} else { 
    if ($stmt = $mysqli->prepare("INSERT INTO `accounts`(`firstname`, `username`, `password`, `email`, `ip`) VALUES (?,?,?,?,?)")) { 

     $stmt->bind_param("sssss", $firstname, $username, password_hash($password1, PASSWORD_BCRYPT), $email, $ip); 
     if($stmt->execute()) { 
      header('Location: /login.html'); 
      $stmt->close(); 
     } else { 
      die($mysqli->error); 
     }  
    } 
} 
+0

什麼你說的是有道理的。但我有點困惑在哪裏把我的那些已經在'if($ stmt-> num_rows> 0)' – DanMossa 2014-12-13 09:24:36

+0

@ Dgameman1我已經修改了一些部分,希望這可以消除一些光 – Ghost 2014-12-13 09:33:19

+0

它需要用戶登錄頁面,但不會將它們添加到數據庫中。即使用戶存在與否。 – DanMossa 2014-12-13 09:58:18