PHP MySQL 준비 문
준비된 문은 SQL 주입에 대해 매우 유용합니다.
준비된 명령문 및 바인딩된 매개변수
준비된 문은 동일한(또는 유사한) SQL 문을 고효율로 반복적으로 실행하는 데 사용되는 기능입니다.
준비된 문은 기본적으로 다음과 같이 작동합니다.
- 준비: SQL 문 템플릿이 생성되어 데이터베이스로 전송됩니다. 특정 값은 매개변수("?"로 표시됨)라고 하는 지정되지 않은 상태로 남아 있습니다. 예: INSERT INTO MyGuests VALUES(?, ?, ?)
- 데이터베이스는 SQL 문 템플릿에 대해 구문 분석, 컴파일 및 쿼리 최적화를 수행하고 실행하지 않고 결과를 저장합니다.
- 실행: 나중에 애플리케이션이 값을 매개변수에 바인딩하고 데이터베이스가 명령문을 실행합니다. 응용 프로그램은 다른 값으로 원하는 만큼 명령문을 실행할 수 있습니다.
SQL 문을 직접 실행하는 것과 비교할 때 준비된 문에는 세 가지 주요 이점이 있습니다.
- 준비된 문은 쿼리에 대한 준비가 한 번만 수행되므로 구문 분석 시간을 줄입니다(문을 여러 번 실행하더라도).
- 바인딩된 매개 변수는 전체 쿼리가 아닌 매번 매개 변수만 보내야 하므로 서버에 대한 대역폭을 최소화합니다.
- 다른 프로토콜을 사용하여 나중에 전송되는 매개 변수 값을 올바르게 이스케이프할 필요가 없기 때문에 준비된 문은 SQL 주입에 대해 매우 유용합니다. 원본 명령문 템플릿이 외부 입력에서 파생되지 않은 경우 SQL 주입이 발생할 수 없습니다.
MySQLi에서 준비된 명령문
다음 예제는 MySQLi에서 준비된 명령문과 바인딩된 매개변수를 사용합니다.
예(준비된 명령문이 있는 MySQLi)
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// prepare and bind
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname, $email);
// set parameters and execute
$firstname = "John";
$lastname = "Doe";
$email = "[email protected]";
$stmt->execute();
$firstname = "Mary";
$lastname = "Moe";
$email = "[email protected]";
$stmt->execute();
$firstname = "Julie";
$lastname = "Dooley";
$email = "[email protected]";
$stmt->execute();
echo "New records created successfully";
$stmt->close();
$conn->close();
?>
위의 예에서 설명하는 코드 라인:
"INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)"
SQL에서 정수, 문자열, double 또는 blob 값으로 대체하려는 위치에 물음표(?)를 삽입합니다.
그런 다음 bind_param() 함수를 살펴보십시오.
$stmt->bind_param("sss", $firstname, $lastname, $email);
이 함수는 매개변수를 SQL 쿼리에 바인딩하고 매개변수가 무엇인지 데이터베이스에 알려줍니다. "sss" 인수는 매개변수가 있는 데이터 유형을 나열합니다. s 문자는 매개변수가 문자열임을 mysql에 알립니다.
인수는 다음 네 가지 유형 중 하나일 수 있습니다.
- 나는 - 정수
- d - 더블
- s - 문자열
- b - BLOB
각 매개변수에 대해 이 중 하나가 있어야 합니다.
mysql에 어떤 유형의 데이터가 예상되는지 알려줌으로써 SQL 주입의 위험을 최소화합니다.
참고: 외부 소스(예: 사용자 입력)의 데이터를 삽입하려는 경우 데이터를 삭제하고 유효성을 검사하는 것이 매우 중요합니다.
PDO에서 준비된 진술
다음 예에서는 PDO에서 준비된 명령문과 바인딩된 매개변수를 사용합니다.
예(준비된 명령문이 있는 PDO)
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// prepare sql and bind parameters
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email)
VALUES (:firstname, :lastname, :email)");
$stmt->bindParam(':firstname', $firstname);
$stmt->bindParam(':lastname', $lastname);
$stmt->bindParam(':email', $email);
// insert a row
$firstname = "John";
$lastname = "Doe";
$email = "[email protected]";
$stmt->execute();
// insert another row
$firstname = "Mary";
$lastname = "Moe";
$email = "[email protected]";
$stmt->execute();
// insert another row
$firstname = "Julie";
$lastname = "Dooley";
$email = "[email protected]";
$stmt->execute();
echo "New records created successfully";
} catch(PDOException $e)
{
echo "Error: " . $e->getMessage();
}
$conn = null;
?>