PHP函數 mysql_real_escape_string 與 addslashes 的區別

來源:互聯網
上載者:User

標籤:

addslashes 和 mysql_real_escape_string 都是為了使資料安全的插入到資料庫中而進行的過濾,那麼這兩個函數到底是有什麼區別呢?

首先,我們還是從PHP手冊入手:

手冊上addslashes轉義的字元是單引號(‘)、雙引號(")、反斜線(\)與NUL(NULL 字元)。

mysql_real_escape_string轉義的字元並沒有被提到,只是說了一句:

注意:mysql_real_escape_string() 並不轉義% 和_。

為什麼PHP手冊沒有說呢?因為其實這是個MySql的C的API,所以我們需要查下MySql手冊,上面是這麼說的:

編碼的字元為NUL (ASCII 0)、‘\n‘、‘\r‘、‘\‘、‘‘‘、‘"‘、以及Control-Z(請參見9.1節,“文字值”)。(嚴格地講,MySQL僅需要反斜線和引號字元,用於引用轉義查詢中的字串。該函數能引用其他字元,從而使得它們在記錄檔中具有更好的可讀性)。

MySql手冊上面的話總是令人費解的。 

我們為了更深層次的探究這兩個函數的不同,還是去看一看PHP的源碼吧。

這是PHP的addslashes函數:

PHP_FUNCTION(addslashes)   {        zval **str;       if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) {            WRONG_PARAM_COUNT;        }        convert_to_string_ex(str);       if (Z_STRLEN_PP(str) == 0) {            RETURN_EMPTY_STRING();        }        RETURN_STRING(php_addslashes(Z_STRVAL_PP(str),                                     Z_STRLEN_PP(str),                                     &Z_STRLEN_P(return_value), 0                                     TSRMLS_CC), 0);   }

 很顯然,它調用了 php_addslashes,我們繼續看這個函數,

PHPAPI char *php_addslashes(char *str, int length, int *new_length, int should_free TSRMLS_DC)    {        return php_addslashes_ex(str, length, new_length, should_free, 0 TSRMLS_CC);    }

 結果又是在調用 php_addslashes_ex,我們就像在剝洋蔥一樣,一步一步的接近真理。

PHPAPI char *php_addslashes_ex(char *str, int length, int *new_length, int should_free, int ignore_sybase TSRMLS_DC)    {        /* maximum string length, worst case situation */        char *new_str;        char *source, *target;        char *end;        int local_new_length;                        if (!new_length) {             new_length = &local_new_length;         }        if (!str) {             *new_length = 0;            return str;         }         new_str = (char *) safe_emalloc(2, (length ? length : (length = strlen(str))), 1);         source = str;         end = source + length;         target = new_str;                if (!ignore_sybase && PG(magic_quotes_sybase)) {            while (source < end) {                switch (*source) {                    case ‘\0‘:                         *target++ = ‘\\‘;                         *target++ = ‘0‘;                        break;                    case ‘\‘‘:                         *target++ = ‘\‘‘;                         *target++ = ‘\‘‘;                        break;                    default:                         *target++ = *source;                        break;                 }                 source++;             }         } else {            while (source < end) {                switch (*source) {                    case ‘\0‘:                         *target++ = ‘\\‘;                         *target++ = ‘0‘;                        break;                    case ‘\‘‘:                    case ‘\"‘:                    case ‘\\‘:                         *target++ = ‘\\‘;                        /* break is missing *intentionally* */                    default:                         *target++ = *source;                        break;                 }                             source++;             }         }                 *target = 0;         *new_length = target - new_str;        if (should_free) {             STR_FREE(str);         }         new_str = (char *) erealloc(new_str, *new_length + 1);        return new_str;    }

 

上面的函數已經非常清楚的描述出都要轉義哪些字元了,現在我們去看一看 mysql_real_escape_string

這個不在string.c裡了,是在mysql擴充中。

PHP_FUNCTION(mysql_real_escape_string)    {         zval *mysql_link = NULL;        char *str;        char *new_str;        int id = -1, str_len, new_str_len;         php_mysql_conn *mysql;        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &str, &str_len, &mysql_link) == FAILURE) {            return;         }        if (ZEND_NUM_ARGS() == 1) {             id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);             CHECK_LINK(id);         }         ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);         new_str = safe_emalloc(str_len, 2, 1);         new_str_len = mysql_real_escape_string(&mysql->conn, new_str, str, str_len);         new_str = erealloc(new_str, new_str_len + 1);         RETURN_STRINGL(new_str, new_str_len, 0);    }

 

這個函數並沒有像上面的那樣剝洋蔥,而是直接調用了MySql的C的API,mysql_real_escape_string()。

需要注意的是,這個函數在調用 mysql_real_escape_string 這個API之前,先是判斷了是否串連上了資料庫,

CHECK_LINK(id);   // 就是這句

 所以,這就意味著 mysql_real_escape_string 必須是串連資料庫之後才能使用。為了證實這一點,我們來簡單的實驗下:

<?phpecho mysql_real_escape_string("fdsafda‘fdsa");

 結果:

Warning: mysql_real_escape_string() [function.mysql-real-escape-string]: Access denied for user ‘ODBC‘@‘localhost‘ (using password: NO) in PHPDocument1 on line 2  Warning: mysql_real_escape_string() [function.mysql-real-escape-string]: A link to the server could not be established in PHPDocument1 on line 2

 

果然報錯了,顯示沒有連結上資料庫。

好了,總結就先告一段落。

終於明白為什麼那麼多開源的程式比如 Discuz 用 addslashes 而不用 mysql_real_escape_string 了。

所以呢,以後也就用 addslashes 好了,暫時可以忘記掉 mysql_real_escape_string 了!

PHP函數 mysql_real_escape_string 與 addslashes 的區別

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.