2016-08-28 2 views
3

Итак, у меня много проблем с подготовленными заявлениями. Я провел много исследований и все еще не могу полностью понять все ...MySQL Подготовлено заявление путаницы

Я действительно чувствую, что мне нужно понять Подготовленные утверждения, потому что я как раз собирался выпустить несколько новых бесплатных API на моем сайте (которые требуют API-интерфейса для выполнения API), но я недавно понял, насколько все это небезопасно .... Я просто могу использовать SQL-инъекцию для обхода проверки API-ключа, например 'OR'1'='1

Вот как я проверить API Key:

$apikey = $_GET['key']; 
$sql = "SELECT * FROM `table` WHERE `key` = '$apikey'"; 
$query = mysqli_query($con, $sql); 
if($query) 
{ 
    $fetchrow = mysqli_fetch_row($query); 
    if(isset($fetchrow[0])) 
    { 
     echo "API Key is valid!"; 
    } 
    else 
    { 
     echo "API KEY is invalid"; 
    } 
} 

И, как упоминалось выше, это можно легко обойти, выполнив свой API, как этот

http://website.com/api.php?key='OR'1'='1 

Это действительно испугало меня в первый, но то я сделал некоторые исследования и научился хорошо предотвращать любую форму SQL-инъекции, чтобы использовать подготовленную инструкцию, поэтому я провел много исследований, и мне это просто кажется довольно сложным:/

Итак, я думаю, мой вопрос в том, как я могу взять мой код выше и заставить его работать одинаково с помощью подготовленных операторов?

+1

Безопасность не из подготовленных операторов, а из использования привязки параметров. См. Http://bobby-tables.com/php.html, например, код. –

+0

Возможный дубликат [Как предотвратить SQL-инъекцию в PHP?] (Http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php) –

+0

@ AlexanderO'Mara lol ...... Может быть, прочитайте чей-то вопрос, прежде чем сказать, что это возможный дубликат .................. – JeffCoderr

ответ

3

Наверное все, что вам нужно:

class Database { 
    private static $mysqli; 

Подключение к БД:

public static function connect(){ 
    if (isset(self::$mysqli)){ 
     return self::$mysqli; 
    } 
    self::$mysqli = new mysqli("DB_HOST", "DB_USER", "DB_PASS", "DB_NAME"); 
    if (mysqli_connect_errno()) { 
     /*Log error here, return 500 code (db connection error) or something... Details in $mysqli->error*/ 
    } 
    self::$mysqli->query("SET NAMES utf8"); 
    return self::$mysqli; 
} 

Execute заявление и получить результаты:

public static function execute($stmt){ 
    $stmt->execute(); 
    if ($mysqli->error) { 
     /*Log it or throw 500 code (sql error)*/ 
    } 
    return self::getResults($stmt); 
} 

результаты связываются с чистого массива: конец

private static function getResults($stmt){ 
    $stmt->store_result(); 
    $meta = $stmt->result_metadata(); 

    if (is_object($meta)){ 
     $variables = array(); 
     $data = array(); 

     while($field = $meta->fetch_field()) { 
      $variables[] = &$data[$field->name]; 
     } 

     call_user_func_array(array($stmt, "bind_result"), $variables); 

     $i = 0; 
     while($stmt->fetch()) { 
      $array[$i] = array(); 
      foreach($data as $k=>$v) 
      $array[$i][$k] = $v; 
      $i++; 
     } 
     $stmt->close(); 
     return $array; 
    } else { 
     return $meta; 
    } 
} 

Класс :)

} 

Пример использования:

public function getSomething($something, $somethingOther){ 
    $mysqli = Database::connect(); 
    $stmt = $mysqli->prepare("SELECT * FROM table WHERE something = ? AND somethingOther = ?"); 
    $stmt->bind_param("si", $something, $somethingOther); // s means string, i means number 
    $resultsArray = Database::execute($stmt); 
    $someData = $resultsArray[0]["someColumn"]; 
} 

Решение вашей проблемы:

public function isKeyValid($key){ 
    $mysqli = Database::connect(); 
    $stmt = $mysqli->prepare("SELECT * FROM table WHERE key = ? LIMIT 1"); 
    $stmt->bind_param("s", $key); 
    $results = Database::execute($stmt); 
    return count($results > 0); 
} 

PHP автоматически закрывает соединение DB поэтому не стоит беспокоиться об этом.