준비된 명령문은 MySQL 주입을 방지하는 데 매우 유용합니다.
준비된 문 및 바인딩된 매개변수
준비된 문은 여러 개의 동일한 SQL 문을 보다 효율적으로 실행하는 데 사용됩니다.
준비된 명령문은 다음과 같이 작동합니다.
전처리: SQL 문 템플릿을 생성하여 데이터베이스로 보냅니다. 예약된 값은 "?"라는 매개변수로 표시됩니다. 예를 들어:
MyGuests(이름, 성, 이메일)에 삽입 VALUES(?, ?, ?)
데이터베이스 구문 분석, 컴파일, SQL 문 템플릿에 대한 쿼리 최적화 및 출력 없이 결과 저장.
실행: 마지막으로 애플리케이션에 바인딩된 값이 매개변수("?" 표시)에 전달되고 데이터베이스가 해당 명령문을 실행합니다. 매개변수 값이 다를 경우 애플리케이션은 해당 명령문을 여러 번 실행할 수 있습니다.
SQL 문을 직접 실행하는 것과 비교할 때 준비된 문에는 두 가지 주요 이점이 있습니다.
준비된 문은 단 하나의 쿼리만 작성되므로 분석 시간이 크게 단축됩니다(문이 여러 번 실행되더라도).
매개변수를 바인딩하면 서버 대역폭이 줄어들므로 전체 문 대신 쿼리 매개변수만 보내면 됩니다.
준비된 문은 매개변수 값이 전송된 후 서로 다른 프로토콜을 사용하여 데이터의 유효성을 보장하므로 SQL 주입에 매우 유용합니다.
MySQLi 준비문
다음 예에서는 MySQLi의 준비된 문을 사용하고 해당 매개변수를 바인딩합니다.
예(MySQLi는 준비된 문을 사용합니다)
<?php $servername = " localhost " ; $username = " 사용자 이름 " ; $password = " 비밀번호 " ; $ dbname = " myDB " ; $conn = 새로운 mysqli ( $servername , $username , $password , $dbname ) ; // 연결 감지 만약에 ( $conn -> 연결_오류 ) { die ( " 연결 실패: " . $conn - > connect_error ) ; // 전처리 및 바인딩 $stmt = $conn -> prepare ( " MyGuests에 삽입(이름, 성, 이메일) VALUES (?, ?, ?) " ) $ stmt -> bind_param ( " sss " , $firstname , $lastname , $email ) ; // 매개변수 설정 및 실행 $ firstname = " John " ; $ email = " [email protected] " ; $ stmt - > 실행 ( ) $ lastname = " Moe " ; " [email protected] " ; $ stmt - > 실행 ( ) ; $ firstname = " Julie " ; $ email = " [email protected] " ; $stmt - > 실행 ( ) ; " 새 레코드가 성공적으로 삽입되었습니다 " ; $ stmt -> close ( ) ; $conn -> close ( ) ; 다음 예제의 각 코드 줄을 구문 분석합니다.
"MyGuests(이름, 성, 이메일) VALUES(?, ?, ?)에 삽입하세요."
SQL 문에서는 물음표(?)를 사용합니다. 여기서 물음표를 정수, 문자열, 배정밀도 부동 소수점 및 부울 값으로 바꿀 수 있습니다.
다음으로, Bind_param() 함수를 살펴보겠습니다.
$stmt->bind_param("sss", $firstname, $lastname, $email);
이 함수는 SQL 매개변수를 바인딩하고 데이터베이스에 매개변수 값을 알려줍니다. "sss" 매개변수 열은 나머지 매개변수의 데이터 유형을 처리합니다. s 문자는 데이터베이스에 매개변수가 문자열임을 알려줍니다.
매개변수에는 네 가지 유형이 있습니다.
i - 정수(정수형)
d - double(이중 정밀도 부동 소수점 유형)
s - 문자열
b - BLOB(이진 대형 개체: 이진 대형 개체)
각 매개변수에는 지정된 유형이 필요합니다.
데이터베이스에 매개변수의 데이터 유형을 알려줌으로써 SQL 주입 위험을 줄일 수 있습니다.
| 참고: 다른 데이터(사용자 입력)를 삽입하려면 데이터 유효성 검사가 매우 중요합니다. |
---|
PDO의 준비된 진술
다음 예에서는 PDO에서 준비된 문과 바인드 매개변수를 사용합니다.
예(PDO는 준비된 문을 사용합니다)
<?php $ servername = " localhost " ; $ username = " 사용자 이름 " ; $ password = " myDBPDO " ; { $conn = 새로운 PDO ( " mysql:host= $servername ;dbname= $dbname " , $username , $password ) ; // PDO 오류 모드를 예외로 설정합니다. $conn -> setAttribute ( PDO :: ATTR_ERRMODE , PDO :: ERRMODE_EXCEPTION ) ; // SQL 및 바인드 매개변수 전처리 $stmt = $conn -> prepare ( " MyGuests
에 삽입(이름, 성, 이메일) VALUES (:firstname, :lastname, :email) " ) $stmt - > binParam ( ' :firstname ' , $firstname ) $ stmt- > bindParam ( ' :lastname ' , $lastname ) ; $stmt- > bindParam ( ' :email ' , $email ) ; // 행 삽입 $firstname = " John " ; $lastname = " Doe " ; $email = " [email protected] " ; $ stmt - > 실행 ( ) ; $firstname = " Mary " ; $lastname = " Moe " ; $email = " [email protected] " ; $ stmt - > 실행 ( ) ; $ firstname = " 줄리 " ; $ lastname = " 둘리 " ; $ email = " [email protected] " ; " 새 레코드가 성공적으로 삽입되었습니다 . " } 잡기 ( PDO예외 $e ) { 에코 " 오류: " . $e - > getMessage ( ) ; $콘 = 널 ? >