기존의 mysql_connect, mysql_query 방법을 사용하여 쿼리 데이터베이스를 접속할 경우 필터링이 잘 되지 않으면 SQL 주입 위험이 있습니다.사용자가 제출한 값은 mysql_real_escape_string() 함수로 필터링할 수 있지만 결함도 있다.PHP의 PDO 확장 prepare 방법을 사용하면 sql injection 리스크를 피할 수 있습니다.
PDO(PHP Data Object)는 PHP5 이전의 php4/php3는 각각 php_mysql.dll과 같은 데이터베이스와 연결 및 처리를 위해 확장되었기 때문에 PHP5에 새로 추가된 중요한 기능입니다. PHP6에서도 기본적으로 PDO 방식으로 연결되며, mysql 확장을 보조로 사용합니다
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");
기본적으로 긴 연결은 아닙니다. 긴 연결을 사용하려면 다음 매개 변수를 입력하십시오
$dbh = new PDO("mysql:host=localhost;dbname=mydb","root","password","array(PDO::ATTR_PERSISTENT => true) ");
$dbh = null; //(석방하다)
. PDO 속성 설정
PDO에는 세 가지 오류가 있습니다방식:
PDO::ERrmODE_SILENT 에러 없음정보, 오류 코드만 설정
PDO::ERrmODE_WARNING 경고 표시틀리다.
PDO::ERrmODE_EXCEPTION 드롭이상하다.
다음 문장으로 설정할 수 있습니다오류처리방식은 드롭아웃 이상
$db->setAttribute(PDO::ATTR_ERrmODE, PDO::ERrmODE_EXCEPTION);
데이터베이스에 따라 반환되는 필드 이름의 대소문자 처리가 다르기 때문에 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::prepare( )에서 DELEETE, INSERT, UPDATE 동작에 영향을 준 결과 세트에 주로 사용되며 PDO::exec() 방법과 SELECT 동작에는 유효하지 않습니다.
5.PDO 작업MYSQL 데이터베이스 인스턴스
<?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 );
}
?>
몇 줄의 데이터가 있는지 집계합니다
<?php
$sql="select count(*) from table";
$num = $dbh->query($sql)->fetchColumn();
?>
prepare 방식:
<?php
$query = $dbh->prepare("select * from table");
if ($query->execute()) {
while ($row = $query->fetch()) {
print_r($row);
}
}
?>
prepare 매개 변수화 쿼리:
<?php
$query = $dbh->prepare("select * from table where id = ?");
if ($query->execute(array(1000))) {
while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
print_r($row);
}
}
?>
PDO를 사용하여 MySQL 데이터베이스에 접속할 경우, 실제 real prepared statements는 기본적으로 사용되지 않습니다.이 문제를 해결하려면 prepared statements 에뮬레이션 효과를 비활성화해야 합니다.다음은 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;
'개발 꿀팁 > PHP' 카테고리의 다른 글
php soap 사용 사례 (0) | 2022.08.18 |
---|---|
php unserialize false 해결 방법 반환 (0) | 2022.08.17 |
php 빈 디렉터리 및 빈 하위 디렉터리 삭제 (0) | 2022.08.17 |
php 페이지의 지정된 내용 클래스 (0) | 2022.08.17 |
PHP 트래버스 폴더 및 파일류 및 처리류 (0) | 2022.08.17 |