여러 쿼리에 대한 PDO 지원 (PDO_MYSQL, PDO_MYSQLND)
PHP여러 쿼리에 대한 PDO 지원 (PDO_MYSQL, PDO_MYSQLND)
PDO가 하나의 명령문에서 실행되는 여러 쿼리를 지원하지 않는다는 것을 알고 있습니다. 나는 Googleing을 해왔고 PDO_MYSQL 및 PDO_MYSQLND에 관한 몇 가지 게시물을 발견했습니다.
From : PDO 및 Zend Framework를 사용한 SQL 삽입 방지 (Julian, 2010 년 6 월)
PDO_MYSQL 및 PDO_MYSQLND가 여러 쿼리에 대한 지원을 제공하는 것처럼 보이지만, 더 많은 정보를 찾을 수 없습니다. 이 프로젝트가 중단 되었습니까? PDO를 사용하여 여러 개의 쿼리를 실행하는 방법이 있습니까?
해결법
-
==============================
1.
PDO_MYSQLND는 PHP 5.3에서 PDO_MYSQL을 대체했습니다. 혼란스러운 부분은 그 이름이 여전히 PDO_MYSQL이라는 것입니다. 이제 ND는 MySQL + PDO의 기본 드라이버입니다.
전반적으로 한 번에 여러 쿼리를 실행하려면 다음이 필요합니다.
exec 사용하기
$db = new PDO("mysql:host=localhost;dbname=test", 'root', ''); // works regardless of statements emulation $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); $sql = " DELETE FROM car; INSERT INTO car(name, type) VALUES ('car1', 'coupe'); INSERT INTO car(name, type) VALUES ('car2', 'coupe'); "; try { $db->exec($sql); } catch (PDOException $e) { echo $e->getMessage(); die(); }
문장 사용하기
$db = new PDO("mysql:host=localhost;dbname=test", 'root', ''); // works not with the following set to 0. You can comment this line as 1 is default $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); $sql = " DELETE FROM car; INSERT INTO car(name, type) VALUES ('car1', 'coupe'); INSERT INTO car(name, type) VALUES ('car2', 'coupe'); "; try { $stmt = $db->prepare($sql); $stmt->execute(); } catch (PDOException $e) { echo $e->getMessage(); die(); }
에뮬레이트 된 준비 문을 사용할 때 DSN (5.3.6부터 사용 가능)에서 올바른 인코딩 (실제 데이터 인코딩을 반영 함)을 설정했는지 확인하십시오. 그렇지 않으면 이상한 인코딩이 사용되면 SQL 주입에 약간의 가능성이있을 수 있습니다.
-
==============================
2.
이 작업을 반나절 만에 PDO에 버그가 있다는 것을 알았습니다.
--
//This would run as expected: $pdo->exec("valid-stmt1; valid-stmt2;");
--
//This would error out, as expected: $pdo->exec("non-sense; valid-stmt1;");
--
//Here is the bug: $pdo->exec("valid-stmt1; non-sense; valid-stmt3;");
"valid-stmt1;"을 실행하고 "non-sense;"를 중지합니다. 결코 오류를 던지지 마십시오. "valid-stmt3;"을 실행하지 않고 true를 반환하고 모든 것이 올바르게 실행되었다고 거짓말을합니다.
나는 그것이 "비 감각 (non-sense)"에서 오류를 범할 것이라고 기대할 것이다. 그러나 그렇지 않습니다.
다음은이 정보를 찾은 곳입니다. 잘못된 PDO 쿼리가 오류를 반환하지 않습니다.
다음은 버그입니다. https://bugs.php.net/bug.php?id=61613
-
==============================
3.
신속하고 더러운 접근 :
function exec_sql_from_file($path, PDO $pdo) { if (! preg_match_all("/('(\\\\.|.)*?'|[^;])+/s", file_get_contents($path), $m)) return; foreach ($m[0] as $sql) { if (strlen(trim($sql))) $pdo->exec($sql); } }
합리적인 SQL 문 끝점에서 분할합니다. 오류 검사도없고 주입 보호도 없습니다. 사용하기 전에 사용법을 이해하십시오. 개인적으로 통합 테스트를 위해 원시 마이그레이션 파일을 시드하는 데 사용합니다.
-
==============================
4.
이 함수를 사용해보십시오 : 다중 쿼리와 다중 값 삽입.
function employmentStatus($Status) { $pdo = PDO2::getInstance(); $sql_parts = array(); for($i=0; $i<count($Status); $i++){ $sql_parts[] = "(:userID, :val$i)"; } $requete = $pdo->dbh->prepare("DELETE FROM employment_status WHERE userid = :userID; INSERT INTO employment_status (userid, status) VALUES ".implode(",", $sql_parts)); $requete->bindParam(":userID", $_SESSION['userID'],PDO::PARAM_INT); for($i=0; $i<count($Status); $i++){ $requete->bindParam(":val$i", $Status[$i],PDO::PARAM_STR); } if ($requete->execute()) { return true; } return $requete->errorInfo(); }
-
==============================
5.
시도한 코드
$db = new PDO("mysql:host={$dbhost};dbname={$dbname};charset=utf8", $dbuser, $dbpass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
그때
try { $db->query('SET NAMES gbk'); $stmt = $db->prepare('SELECT * FROM 2_1_paidused WHERE NumberRenamed = ? LIMIT 1'); $stmt->execute(array("\xbf\x27 OR 1=1 /*")); } catch (PDOException $e){ echo "DataBase Errorz: " .$e->getMessage() .'<br>'; } catch (Exception $e) { echo "General Errorz: ".$e->getMessage() .'<br>'; }
그리고있어.
DataBase Errorz: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '/*' LIMIT 1' at line 1
$ db-> setAttribute를 추가하면 (PDO :: ATTR_EMULATE_PREPARES, false); $ db = 후 ...
그런 다음 빈 페이지가 있습니다.
SELECT 대신 DELETE를 시도하면 두 경우 모두 다음과 같은 오류가 발생합니다.
DataBase Errorz: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '* FROM 2_1_paidused WHERE NumberRenamed = '¿\' OR 1=1 /*' LIMIT 1' at line 1
그래서 아무런 주입도 할 수 없다는 결론을 내 렸습니다.
from https://stackoverflow.com/questions/6346674/pdo-support-for-multiple-queries-pdo-mysql-pdo-mysqlnd by cc-by-sa and MIT lisence
'PHP' 카테고리의 다른 글
PHP의 전역 변수가 나쁜 습관으로 간주됩니까? 그렇다면 왜? (0) | 2018.09.02 |
---|---|
PHP에서 eval 악마는 언제입니까? (0) | 2018.09.02 |
PHP는 백그라운드 프로세스를 실행 (0) | 2018.09.02 |
PHP로 POST 요청을 보내려면 어떻게해야합니까? (0) | 2018.09.02 |
PDO 연결을 올바르게 설정하는 방법 (0) | 2018.09.02 |