mysql_real_escape_string보다 mysql 쿼리/쿼리 스트링을 탈출하는 데 PDO가 더 나은 이유는 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1742066

문제

나는 내가 더 잘 사용할 것이라고 들었습니다 PDO MySQL 이하의 경우 mysql_real_escape_string.

어쩌면 나는 두뇌의 날을 보내고 있을지도 모른다 (또는 자연 프로그래머라는 상상력이 없다는 사실이 사실 일 수도 있고, PHP와 관련하여 여전히 초보자 단계에 있습니다). PHP 매뉴얼을 확인하고 읽으십시오 PDO의 항목, 나는 여전히 PDO가 실제로 무엇인지, 왜 사용하는 것보다 더 나은지에 대해 더 명확하지 않습니다. mysql_real_escape_string. 이것은 아직 OOP의 복잡성을 실제로 잡지 못했기 때문일 수 있습니다 (OOP와 관련이 있다고 가정합니다). 변수와 배열 값이 결장을 가졌다는 사실 외에는 다른 것입니다. 나는 여전히 그것이 무엇인지, 그리고 당신이 그것을 어떻게 사용하는지 확실하지 않습니다 (그리고 그것이 왜 더 나은지 mysql_real_escape_string. (또한 '클래스'가 무엇인지 명확하게 이해하지 못한다는 사실과 관련이있을 수 있습니다. 그래서 "PDO 클래스"를 읽을 때 나는 실제로 더 현명하지 않습니다).

읽은 기사 또는 MySQL 웹 사이트의 '개발자 영역'비트에서 두 개는 여전히 명확하지 않습니다. 지금은 무엇인지 알 수 없기 때문에 아마도 그것을 사용하는 것이 지금은 조금 넘어 졌다고 생각하지만 여전히 교육을 넓히고 어떻게 개선 할 수 있는지 알아내는 데 관심이 있습니다.

누구든지 '평범한 영어'에서 나에게 pdo가 무엇인지 (또는 평범한 영어로 작성된 주제에 관한 방향을 가리키는 지), 그리고 어떻게 그것을 사용하는지 설명 할 수 있습니까?

도움이 되었습니까?

해결책

귀하의 질문이 일반적인 개요를 더 목표로하는 동안 현재 답변이 자세히 설명하므로 다음과 같이 시도해 보겠습니다.

PDO 클래스는 데이터베이스와 상호 작용하는 데 필요한 모든 기능을 캡슐화하는 것을 목표로합니다. 그들은 '메소드'(기능을위한 oogllor) 및 '속성'(변수에 대한 팔러)을 정의함으로써이를 수행합니다. 당신은 그것들을 a로 사용할 것입니다 완전한 교체 데이터베이스와 대화하기 위해 현재 사용하고있는 모든 '표준'기능에 대해.

따라서 일련의 'mysql_dosomething () 함수를 호출하는 대신 결과를 자신의 변수에 저장하는 대신 PDO 클래스에서 개체를'인스턴스화 '합니다 ('class '= arbost 정의'= 개체, 사용 가능한 인스턴스 클래스)의) 및 해당 객체의 메소드를 호출하여 동일한 작업을 수행합니다.

예를 들어, PDO가 없으면 다음과 같은 일을 할 것입니다.

// Get a db connection
$connection = mysql_connect('someHost/someDB', 'userName', 'password');
// Prepare a query
$query = "SELECT * FROM someTable WHERE something = " . mysql_real_escape_string($comparison) . "'";
// Issue a query
$db_result = mysql_query($query);
// Fetch the results
$results = array();
while ($row = mysql_fetch_array($db_result)) {
  $results[] = $row;
}

이것은 PDO를 사용하는 동등한 일입니다.

// Instantiate new PDO object (will create connection on the fly)
$db = new PDO('mysql:dbname=someDB;host=someHost');
// Prepare a query (will escape on the fly)
$statement = $db->prepare('SELECT * FROM someTable WHERE something = :comparison');
// $statement is now a PDOStatement object, with its own methods to use it, e.g.
// execute the query, passing in the parameters to replace
$statement->execute(array(':comparison' => $comparison));
// fetch results as array
$results = $statement->fetchAll();

따라서 언뜻보기에 구문을 제외하고는 큰 차이가 없습니다. 그러나 PDO 버전에는 몇 가지 장점이 있으며 가장 큰 것은 데이터베이스 독립성입니다.

대신 PostgreSQL 데이터베이스와 대화 해야하는 경우 mysql:에게 pgsql: 인스턴스팅하는 전화에서 new PDO(). 기존 방법을 사용하면 모든 코드를 거쳐 모든 'MySQL_DOSOMETHENG () 함수를'PG_DOSOMTHING () '대응 물 (항상 매개 변수 처리의 잠재적 차이를 확인하는)으로 대체해야합니다. 다른 많은 지원되는 데이터베이스 엔진의 경우도 마찬가지입니다.

따라서 귀하의 질문으로 돌아 가기 위해 PDO는 기본적으로 동일한 것을 달성 할 수있는 다른 방법을 제공하면서 바로 가기/개선/장점을 제공합니다. 예를 들어, 탈출은 사용중인 데이터베이스 엔진에 필요한 적절한 방법으로 자동으로 발생합니다. 또한 파라미터 대체 (예제에 표시되지 않은 SQL 주입을 방지)가 훨씬 쉬워 오류가 덜 발생합니다.

당신은 읽어야합니다 일부 OOP 기본 사항 다른 장점에 대한 아이디어를 얻으려면.

다른 팁

나는 PDO에 매우 익숙하지는 않지만 "준비된 진술"과 탈출 된 문자열 사이에는 차이가 있습니다. 탈출은 거의 없습니다 허용되지 않은 문자열 제거 쿼리에서, 그러나 준비된 진술은 거의 없습니다 데이터베이스에 어떤 종류의 쿼리를 기대 해야하는지 알려줍니다.

쿼리에는 여러 부분이 있습니다

이런 식으로 생각하십시오 : 데이터베이스에 쿼리를 줄 때, 당신은 몇 가지 별도의 것들을 말하고 있습니다. 예를 들어, "나는 당신이 선택을하기를 원합니다."입니다. 다른 하나는 "사용자 이름이 다음 값인 행으로 제한 할 수 있습니다."

문자열로 쿼리를 구축하여 데이터베이스에 건네 주면 완성 된 문자열이 가져올 때까지 어느 부분에 대해 알 수 없습니다. 당신은 이것을 할 수 있습니다 :

'SELECT * FROM transactions WHERE username=$username'

그것이 그 줄을 얻을 때, 그것은 그것을 구문 분석하고 결정해야한다 "이것은"이것은 " SELECT a WHERE".

부품을 혼합합니다

악의적 인 사용자가 사용자 이름을 입력한다고 가정합니다 billysmith OR 1=1. 조심하지 않으면 문자열에 넣을 수 있습니다.

'SELECT * FROM transactions WHERE username=billysmith OR 1=1'

... 돌아올 것입니다 모든 사용자를위한 모든 거래, 1은 항상 1과 같습니다. whops, 당신은 해킹당했습니다!

무슨 일이 있었는지 보시겠습니까? 데이터베이스는 쿼리에서 어떤 부품을 기대 해야하는지 몰랐습니다., 그래서 그것은 단지 문자열을 구문 분석했습니다. 그게 놀라지 않았습니다 WHERE 있었어 OR, 그것을 만족시킬 수있는 두 가지 조건으로.

부품을 똑바로 유지합니다

그것이 알고 있었다면 뭘 기대 할까, 즉, a SELECT 누구 WHERE 하나의 조건 만 있었지만 악의적 인 사용자는 그것을 속일 수 없었습니다.

준비된 진술을 통해 올바른 기대를 줄 수 있습니다. 당신은 데이터베이스에 "내가 당신에게 보내려고합니다 SELECT, 그리고 그것은 줄로 제한 될 것입니다 WHERE username = 내가 당신에게 줄 끈. 그게 전부입니다 - 쿼리에는 다른 부분이 없습니다. 준비 되었나요? 좋아, 여기에 사용자 이름과 비교할 문자열이 온다. "

그 기대에 따라 데이터베이스는 속지 않을 것입니다. username 열에는 실제 문자열 'Billysmith 또는 1 = 1'이 포함되어 있습니다. 아무도 그 사용자 이름을 가지고 있지 않다면 아무것도 반환하지 않을 것입니다.

준비된 진술의 기타 이점

보안 혜택 외에도 준비된 진술에는 몇 가지 속도 이점이 있습니다.

  • 데이터베이스는 이미 기본적으로 요청하려는 것을 알고 있기 때문에 새로운 쿼리를 처음부터 처음부터 구축하는 것보다 빠른 매개 변수로 재사용 할 수 있습니다. 이미 "쿼리 계획"을 구축했습니다.
  • 일부 데이터베이스 (Postgres는 하나입니다. 따라서 첫 번째 쿼리에서도 속도가 빨라질 수 있습니다.

다른 설명은 Theo의 답변을 참조하십시오 여기.

mysql_real_escape_string과 달리 PDO를 사용하면 데이터 유형을 시행 할 수 있습니다.

<?php
/* Execute a prepared statement by binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour');
$sth->bindParam(':calories', $calories, PDO::PARAM_INT);
$sth->bindParam(':colour', $colour, PDO::PARAM_STR, 12);
$sth->execute();
?>

위의 예에서 첫 번째 매개 변수 인 칼로리는 정수 (pdo :: param_int)가 필요합니다.

둘째, PDO 매개 변수화 된 쿼리는 읽기가 더 쉽습니다. 차라리 읽고 싶습니다 :

SELECT name FROM user WHERE id = ? AND admin = ? 

~보다

SELECT name FROM user WHERE id = mysql_real_escape_string($id) AND admin = mysql_real_escape_string($admin);

셋째, 매개 변수를 올바르게 인용 할 필요가 없습니다. PDO는 그것을 처리합니다. 예를 들어, mysql_real_query_string :

SELECT * FROM user WHERE name = 'mysql_real_escape_string($name)' //note quotes around param

vs

SELECT * FROM user WHERE name = ?

마지막으로 PDO를 사용하면 PHP 데이터 호출을 변경하지 않고 앱을 다른 DB로 포트 할 수 있습니다.

라인을 따라 무언가를 쓴다고 상상해보십시오.

$query = 'SELECT * FROM table WHERE id = ' . mysql_real_escape_string($id);

$ id가 1 OR 1=1 그리고 당신은 테이블에서 모든 레코드를 얻을 것입니다. $ ID를 올바른 데이터 유형으로 캐스트해야합니다 (이 경우 int)

PDO는 또 다른 이점이 있으며 이는 데이터베이스 백엔드의 상호 교환 가능성입니다.

SQL 주입을 방지하는 것 외에도 PDO를 사용하면 쿼리를 한 번 준비하고 여러 번 실행할 수 있습니다. 쿼리가 여러 번 실행되면 (예를 들어 루프 내에서)이 방법이 더 효율적이어야합니다 (이전 버전의 MySQL에서는 항상 그렇지 않기 때문에 "해야합니다"). 준비/바인드 방법은 내가 함께 일한 다른 언어와 더 일치합니다.

mysql_real_escape_string보다 mysql 쿼리/쿼리 스트링을 탈출하는 데 PDO가 더 나은 이유는 무엇입니까?

단순히 "탈출"만으로는 의미가 없기 때문입니다.
또한, 다릅니다 비교할 수 없는 문제.

탈출의 유일한 문제는 그 것입니다 모두가 잘못 생각합니다. 일종의 "보호"라고 가정합니다.
모두가 "나는 내 변수를 피했다"는 "쿼리를 보호했다"고 말합니다.
하는 동안 탈출하는 것은 전혀 보호와 관련이 없습니다.

보호는 대략적으로 달성 될 수 있습니다 나는 탈출하여 내 데이터를 인용했다, 그러나 예를 들어 식별자 (예 : PDO뿐만 아니라)에 적용 할 수는 없습니다.

그래서 대답은 다음과 같습니다.

  • PDO는 Bind 값을 탈출 할 때 탈출뿐만 아니라 인용문을 적용합니다. 그래서 그것이 더 나은 이유입니다.
  • "탈출"은 "보호"와 동의어가 아닙니다. "탈출 + 인용"대략.
  • 그러나 일부 쿼리 부품의 경우 두 가지 방법 모두 적용 할 수 없습니다.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top