기존의 mysql_connect 및 mysql_query 메소드를 사용하여 데이터베이스에 연결하고 쿼리할 때 필터링이 엄격하지 않으면 SQL 주입의 위험이 있습니다. mysql_real_escape_string() 함수를 사용하여 사용자가 제출한 값을 필터링할 수 있지만 여기에도 결함이 있습니다. PHP PDO 확장의 prepare 메소드를 사용하면 SQL 인젝션의 위험을 피할 수 있습니다.
PDO(PHP 데이터 개체)는 PHP5에 추가된 새로운 주요 기능입니다. 왜냐하면 PHP 5 이전에는 php4/php3에 php_mysql.dll과 같은 다양한 데이터베이스를 연결하고 처리하기 위한 많은 데이터베이스 확장이 있었기 때문입니다. PHP6은 기본적으로 PDO를 사용하여 연결하며 mysql 확장은 보조로 사용됩니다. 공식 주소: http://php.net/manual/en/book.pdo.php
1. PDO 구성
PDO 확장을 사용하기 전에 먼저 PHP에서 이 확장을 활성화해야 합니다. ini에서 "extension=php_pdo.dll" 앞의 ";" 숫자를 제거해야 합니다. 데이터베이스에 연결하려면 PDO 관련 데이터베이스 확장자(보통 php_pdo_mysql) 앞의 ";" 숫자도 제거해야 합니다. .dll이 사용됨), Apache 서버를 다시 시작할 수 있습니다.
extension=php_pdo.dll extension=php_pdo_mysql.dll
2. PDO는 mysql 데이터베이스에 연결됩니다
$dbh = new PDO("mysql:host=localhost;dbname=mydb","root","password");
기본값은 긴 연결이 아닙니다. 데이터베이스에 대한 긴 연결을 사용하려는 경우 끝에 다음 매개변수를 추가할 수 있습니다.
3. PDO 설정 속성
PDO에는 세 가지 오류 처리 방법이 있습니다.
PDO::ERrmODE_SILENT는 오류 메시지를 표시하지 않고 오류 코드만 설정합니다
PDO::ERrmODE_WARNING은 경고 오류를 표시합니다
PDO::ERrmODE_EXCEPTION에서 예외가 발생함
다음 명령문을 사용하여 예외를 발생시키는 오류 처리 방법을 설정할 수 있습니다.
$dbh = new PDO("mysql:host=localhost;dbname=mydb","root","password","array(PDO::ATTR_PERSISTENT => true) "); $dbh = null; //(释放)
서로 다른 데이터베이스는 반환된 필드 이름의 대소문자를 다르게 처리하므로 PDO는 PDO를 제공합니다. ::ATTR_CASE 설정 항목(PDO::CASE_LOWER, PDO ::CASE_NATURAL, PDO::CASE_UPPER 포함)은 반환된 필드 이름의 대소문자를 결정합니다.
PDO::ATTR_ORACLE_NULLS 유형(PDO::NULL_NATURAL, PDO::NULL_EmpTY_STRING, PDO::NULL_TO_STRING 포함)을 설정하여 데이터베이스에서 반환된 NULL 값의 PHP에서 해당 값을 지정합니다.
4. 일반적인 PDO 메서드 및 해당 응용
PDO::query()는 주로 기록된 결과를 반환하는 작업, 특히 SELECT 작업에 사용됩니다.
PDO::exec() 입니다. INSERT, UPDATE 및 기타 작업과 같이 결과 집합을 반환하지 않는 작업의 경우
PDO::prepare()는 주로 전처리 작업을 실행하기 위해 $rs->execute()를 사용해야 합니다. 전처리의 SQL 문입니다. 이 메서드는 매개 변수를 바인딩할 수 있으며 매우 강력합니다(SQL 주입 방지는 이에 따라 다름).
PDO::lastInsertId()는 마지막 삽입 작업을 반환하고 기본 키 열 유형은 마지막 자동 증가입니다. ID
PDOStatement::fetch()는 레코드를 가져오는 데 사용됩니다.
PDOStatement::fetchAll()은 모든 레코드를 컬렉션으로 가져오는 데 사용됩니다.
PDOStatement::fetchColumn()은 레코드를 가져오는 데 사용됩니다. 결과 필드에 지정된 첫 번째 레코드, 기본값은 첫 번째 필드입니다.
PDOStatement::rowCount(): 주로 PDO::query() 및 PDO의 DELETE, INSERT 및 UPDATE 작업의 영향을 받는 결과 세트에 사용됩니다. ::prepare(). PDO::exec() 메서드 및 SELECT 작업에는 유효하지 않습니다.
5.PDO 작업 MYSQL 데이터베이스 인스턴스
$db->setAttribute(PDO::ATTR_ERrmODE, PDO::ERrmODE_EXCEPTION);
<?php $pdo = new PDO("mysql:host=localhost;dbname=mydb","root",""); if($pdo -> exec("insert into mytable(name,content) values('fdipzone','123456')")){ echo "insert success"; echo $pdo -> lastinsertid(); } ?>
<?php $pdo = new PDO("mysql:host=localhost;dbname=mydb","root",""); $rs = $pdo -> query("select * from table"); $rs->setFetchMode(PDO::FETCH_ASSOC); //关联数组形式 //$rs->setFetchMode(PDO::FETCH_NUM); //数字索引数组形式 while($row = $rs -> fetch()){ print_r($row); } ?>
데이터 행 수 계산:
<?php foreach( $db->query( "SELECT * FROM table" ) as $row ) { print_r( $row ); } ?>
prepare 방법:
<?php $sql="select count(*) from table"; $num = $dbh->query($sql)->fetchColumn(); ?>
prepare 쿼리:
e7aacce4249b65e0c0c47d847f142e63prepare("select * from table"); if ($query->execute()) { while ($row = $query->fetch()) { print_r($row); } } ?>
PDO 사용 MySQL 데이터베이스에 액세스할 때 실제 준비된 명령문은 기본적으로 사용되지 않습니다. 이 문제를 해결하려면 준비된 문의 에뮬레이션 효과를 비활성화해야 합니다. 다음은 PDO를 사용하여 링크를 만드는 예입니다:
<?php $dbh = new PDO('mysql:dbname=mydb;host=127.0.0.1;charset=utf8', 'root', 'pass'); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); ?>
setAttribute()这一行是强制性的,它会告诉 PDO 禁用模拟预处理语句,并使用 real parepared statements 。这可以确保SQL语句和相应的值在传递到mysql服务器之前是不会被PHP解析的(禁止了所有可能的恶意SQL注入攻击)。
虽然你可以配置文件中设置字符集的属性(charset=utf8),但是需要格外注意的是,老版本的 PHP( < 5.3.6)在DSN中是忽略字符参数的。
完整的代码使用实例:
<?php $dbh = new PDO("mysql:host=localhost; dbname=mydb", "root", "pass"); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); //禁用prepared statements的仿真效果 $dbh->exec("set names 'utf8'"); $sql="select * from table where username = ? and password = ?"; $query = $dbh->prepare($sql); $exeres = $query->execute(array($username, $pass)); if ($exeres) { while ($row = $query->fetch(PDO::FETCH_ASSOC)) { print_r($row); } } $dbh = null; ?>
上面这段代码就可以防范sql注入。为什么呢?
当调用 prepare() 时,查询语句已经发送给了数据库服务器,此时只有占位符 ? 发送过去,没有用户提交的数据;当调用到 execute()时,用户提交过来的值才会传送给数据库,它们是分开传送的,两者独立的,SQL攻击者没有一点机会。
但是我们需要注意的是以下几种情况,PDO并不能帮助你防范SQL注入。
不能让占位符 ? 代替一组值,这样只会获取到这组数据的第一个值,如:
select * from table where userid in ( ? );
如果要用in來查找,可以改用find_in_set()实现
$ids = '1,2,3,4,5,6'; select * from table where find_in_set(userid, ?);
不能让占位符代替数据表名或列名,如:
select * from table order by ?;
不能让占位符 ? 代替任何其他SQL语法,如:
select extract( ? from addtime) as mytime from table;
本篇文章如何使用PDO查询mysql避免SQL注入的方法,更多相关内容请关注php中文网。
相关推荐:
关于HTML5 localStorage and sessionStorage 之间的区别
위 내용은 SQL 주입을 피하기 위해 PDO를 사용하여 mysql을 쿼리하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!