1

为了避免 SQL 注入,我尝试使用准备好的语句制作 PHP 脚本。我还创建了 3 个 php 文件。

  1. db_connect.php(这里存储了连接数据库的所有信息)

  2. functions.php(创建会话,检查登录尝试和功能login- 我可能犯了一个错误但找不到它)

  3. process_login.php(上面两个文件的集合。如果没有 POST 变量发送到此页面,它还会重定向到login_success错误页面或打印Invalid request )。

另外可能是错误所在,因为每次尝试插入一些值时我都会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

你只有一个 $variable 可以绑定。您正在尝试绑定两个:

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.
于 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 回答