每一個語言都有本身的數據庫框架或庫,不管是哪一種語言,哪一種庫,它們在數據庫防注入方面使用的技術原理無外乎下面介紹的幾種方法。mysql
Mysql特殊字符指在mysql中具備特殊含義的字符,除了%
和_
是mysql特有的外,其餘的和咱們在C語句中接觸的特殊字符同樣。sql
特殊字符 | 轉義字符 | 特殊意義 |
---|---|---|
\0 |
\\0 |
字符串結束符NUL |
' |
\' |
單引號 |
" |
\" |
雙引號 |
\b |
\\b |
退格 |
\n |
\\n |
換行 |
\r |
\\r |
回車 |
\Z |
\\Z |
Control+Z |
\ |
\\ |
反斜槓 |
% |
\% |
百分號,模糊查詢中匹配任意個任意字符 |
_ |
\_ |
下劃線,模糊查詢中匹配單個任意字符 |
mysql C API提供了mysql_real_escape_string
函數對轉義字符進行處理,但根據實際經驗,在使用該API時會產生諸多問題。
所以本身實現了一個相似的函數:數據庫
std::string MysqlEscapeString(const std::string &strSql) { size_t iSrcSize = strSql.size(); std::string strDest; for (size_t i = 0; i < iSrcSize; i++) { char ch = strSql[i]; switch (ch) { case '\0': strDest.append("\\0"); break; case '\n': strDest.append("\\n"); break; case '\r': strDest.append("\\r"); break; case '\'': strDest.append("\\'"); break; case '"': strDest.append("\\\""); break; case '\\': strDest.append("\\\\"); break; case '%': strDest.append("\\%"); break; case '_': strDest.append("\\_"); break; default: strDest.append(1, ch); break; } } return strDest; }
對於%
和_
這2個只在模糊查詢條件中有特殊含義,而在普通字符串中沒有其餘含義的字符,須要根據字符使用在SQL語句中的具體位置來決定是否須要處理。如咱們要查詢memberName包含t_st的用戶信息:app
select * from member where memberName like '%t_st%;
若是不對_
進行轉義處理則會查詢出:框架
test tast tbst t_st
SET @sql = "SELECT * FROM member WHERE memberName like ?"; SET @param = '%t_st%'; PREPARE stmt FROM @sql; EXECUTE stmt using @param; DEALLOCATE PREPARE stmt;
使用這種方法須要注意如下2點:
1) ?
佔位符不能用在字符串中,上面例子若是寫成下面這樣是錯誤的。函數
SET @sql = "SELECT * FROM member WHERE memberName like '%?%'"; SET @param = 't_st'; PREPARE stmt FROM @sql; EXECUTE stmt using @param; DEALLOCATE PREPARE stmt;
2) EXECUTE stmt USING @param;
中使用的@param變量,是會話級別的變量。該變量的做用域至整個鏈接,鏈接斷開以後該變量纔會釋放。重複使用相同變量時要留意了。code