轉義字符:html、mysql、postgresql、json、php


結論:

1、使用php magic_quotes_gpc是錯誤的。從PHP 5.4.0 起已刪除此功能。http://www.php.net/manual/zh/function.get-magic-quotes-gpc.php

2、使用php addslashes是錯誤的。因為它不對應mysql或pgsql。PHP官方強烈建議使用對應mysql的mysqli_real_escape_string()和對應PostgreSQL的pg_escape_string()。http://php.net/manual/en/function.addslashes.php

3、保存到數據庫之前使用htmlspecialchars是錯誤的。應直接保存到數據庫。通過API提供給手機app看,C++不需要轉義HTML。通過web看時,才需要轉義。見下圖。

4、使用php mysql_escape_string是錯誤的,已廢棄,應使用mysqli::real_escape_stringhttp://php.net/manual/en/function.mysql-escape-string.php

5、數據入庫前根據不同數據庫進行不同的轉義,這放在dao層。controller、model都不應該知道。

錯誤的轉義方式:

正確的轉義方式:

 

詳細分析如下。

為什么要轉義:

1、字符與保留字沖突,比如HTML中的小與號<用於標簽

2、ASCII字符集中沒有此字符,比如HTML中©以前經常寫成&copy;

第2種情況現在已經無需考慮,因為 Windows 從 XP 開始、Linux 從 GNU glibc 2.2 開始,操作系統都支持Unicode字符集了,目前開發程序主流是使用Unicode的utf-8編碼。

本文只討論第1種情況。

需要轉義的內容:

  需要轉義 不需要轉義的字符(常見錯誤)
HTML <、& >
mysql 換行、回車等 換頁、空格、<、>、&
postgresql 換頁、換行、回車等  
JSON "、\和控制字符  

PHP常見轉義方法:

  轉義范圍
不應使用addslashes 單引號'、雙引號"、反斜線\與 NUL
htmlspecialchars &、'、"、<、>
不應使用mysql_escape_string 對應mysql 4
mysqli::real_escape_string 對應mysql 5+
pg_escape_string 對應PostgreSQL
php PDO::quote 自動判斷數據庫是Mysql還是PostgreSQL等
PDO::prepare() 自動判斷數據庫是Mysql還是PostgreSQL等

對字符串"hello world\fjim\n\r"進行轉義,結果如下:

mysqli::real_escape_string

View Code
<?php
$mysqli = new mysqli('localhost', 'root', '1', 'test');
$a = "hello world\fjim\n\r";
var_dump($mysqli->real_escape_string($a));
$sql = "INSERT INTO user VALUES ('2','lucy','". $mysqli->real_escape_string($a) . '\');';
var_dump($sql);
$mysqli->query($sql);
?>

PDO::quote mysql 與 mysqli::real_escape_string 結果一樣。

View Code
<?php
$dsn = 'mysql:dbname=test;host=localhost';
$user = 'root';
$password = '1';
$dbh = new PDO($dsn, $user, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$a = "hello world\fjim\n\r";
var_dump($dbh->quote($a));
$sql = "INSERT INTO user VALUES ('2','lucy',". $dbh->quote($a) . ');';
var_dump($sql);
$stmt = $dbh->query($sql);
exit;
?>

 

 

pg_escape_string

View Code
<?php
$db = pg_connect("host=localhost port=5432 dbname=test user=root password=1");
$a = "hello world\fjim\n\r";
var_dump(pg_escape_string($a));
$sql = "INSERT INTO schema1.user VALUES ('2','lucy','". pg_escape_string($a) . '\');';
var_dump($sql);
pg_query($db, $sql);exit;
?>

PDO::quote pgsql 與pg_escape_string 結果相同。

View Code
<?php
$dsn = 'pgsql:host=localhost;port=5432;dbname=test;user=root;password=1';
$dbh = new PDO($dsn);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$a = "hello world\fjim\n\r";
var_dump($dbh->quote($a));
//$stmt = $dbh->query('SELECT "id","name","desc" FROM schema1."user"');
//$sql = "INSERT INTO schema1.user VALUES ('1','jim','hello world\fjim\n\r');";
$sql = "INSERT INTO schema1.user VALUES ('2','lucy',". $dbh->quote($a) . ');';
var_dump($sql);
$stmt = $dbh->query($sql);
exit;
?>

 

 

 

HTML:

HTML標簽使用小與號<開頭,所以需要轉義。而大與號>不用轉義。官方文檔:http://www.w3.org/TR/xhtml1/#h-4.8

 

mysql:

官方文檔:http://dev.mysql.com/doc/refman/5.1/zh/language-structure.html#string-syntax

mysql在默認的空sql-mode下,value的string使用單引號'或雙引號"引起來,官方文檔:http://dev.mysql.com/doc/refman/5.1/zh/language-structure.html#string-syntax

mysql在默認的空sql-mode下,識別符(庫、表、索引、列和別名)使用反勾號`引起來,官方文檔:http://dev.mysql.com/doc/refman/5.1/zh/language-structure.html#legal-names

mysql在ANSI_QUOTES sql-mode下,value的string使用單引號'引起來,官方文檔:http://dev.mysql.com/doc/refman/5.1/zh/language-structure.html#string-syntax

mysql在ANSI_QUOTES sql-mode下,識別符(庫、表、索引、列和別名)使用雙引號"或反勾號`引起來,http://dev.mysql.com/doc/refman/5.1/zh/database-administration.html#server-sql-mode

這里以默認的空sql-mode為例。

如果string使用雙引號引起來,那么string中的單引號無需轉義。如果string使用單引號引起來,那么string中的雙引號無需轉義。

使用musqldump導出sql就會看到,mysql的string使用單引號'引起來,而雙引號一定被轉義。

比如INSERT INTO `asdf` VALUES ('a\"b'); 和 INSERT INTO `asdf` VALUES ('a"b'); 結果是一樣的。

 

postgresql:

官方文檔:http://wiki.postgresql.org/wiki/9.1%E7%AC%AC%E5%9B%9B%E7%AB%A0#C.E8.AF.AD.E8.A8.80.E4.B8.AD.E7.9A.84.E8.BD.AC.E6.84.8F.E5.AD.97.E7.AC.A6.E4.B8.B2.E5.B8.B8.E9.87.8F.28String_Constants_with_C-style_Escapes.29

value的string使用單引號'引起來或者不引。

識別符(列名等)使用雙引號"引起來或者不引。

 

JSON:

官方文檔:http://www.json.org/json-zh.html

JSON的string,必須使用雙引號"引起來,不能使用單引號'引起來。如果字符串中出現雙引號,需要轉義,比如{"name" : "John \"Cliff\" Barxter"}。

 

參考資料:

http://www.ibm.com/developerworks/cn/linux/i18n/unicode/linuni/

http://msdn.microsoft.com/zh-cn/magazine/cc163490.aspx

采用支持 Unicode 的單源代碼庫使開發時間得以縮短,Unicode 為 Microsoft 帶來的好處是顯而易見的。就 Windows® 2000 來說,在發布英文產品后需要花費幾個月的時間來准備其本地化版本。而對於 Windows XP,這一周期已縮短為幾周時間。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM