对 string 稍作处理, 避免在写 query 的时候被 SQL 注入, 这是常识. 我们若变更 PHP 版本, 有时候会出现 Call To Undefined Function 这样的错误. 很多时候, 我们需要做出一些兼容性的处理.

不过, 若我们是在 WordPress 的平台上写插件, 则不必这么麻烦了.

在 WordPress 环境下, 系统已经为我们提供了一些有趣的 function, 来包装这些兼容性处理. 我们只消如下 fix 即可:

- $dest = mysql_escape_string($src);
+ $dest = esc_sql($src);

这样就已经足够了.

相关代码如下:

/**
 * Escapes data for use in a MySQL query.
 *
 * Usually you should prepare queries using wpdb::prepare().
 * Sometimes, spot-escaping is required or useful. One example
 * is preparing an array for use in an IN clause.
 *
 * @since 2.8.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string|array $data Unescaped data
 * @return string|array Escaped data
 */
function esc_sql( $data ) {
        global $wpdb;
        return $wpdb->_escape( $data );
}
/**
 * Escape data. Works on arrays.
 *
 * @uses wpdb::_real_escape()
 * @since  2.8.0
 * @access private
 *
 * @param  string|array $data
 * @return string|array escaped
 */
function _escape( $data ) {
        if ( is_array( $data ) ) {
                foreach ( $data as $k => $v ) {
                        if ( is_array($v) )
                                $data[$k] = $this->_escape( $v );
                        else
                                $data[$k] = $this->_real_escape( $v );
                }
        } else {
                $data = $this->_real_escape( $data );
        }

        return $data;
}

/**
 * Real escape, using mysqli_real_escape_string() or mysql_real_escape_string()
 *
 * @see mysqli_real_escape_string()
 * @see mysql_real_escape_string()
 * @since 2.8.0
 * @access private
 *
 * @param  string $string to escape
 * @return string escaped
 */
function _real_escape( $string ) {
        if ( $this->dbh ) {
                if ( $this->use_mysqli ) {
                        return mysqli_real_escape_string( $this->dbh, $string );
                } else {
                        return mysql_real_escape_string( $string, $this->dbh );
                }
        }

        $class = get_class( $this );
        if ( function_exists( '__' ) ) {
                /* translators: %s: database access abstraction class, usually wpdb or a class extending wpdb */
                _doing_it_wrong( $class, sprintf( __( '%s must set a database connection for use with escaping.' ), $class ), E_USER_NOTICE );
        } else {
                _doing_it_wrong( $class, sprintf( '%s must set a database connection for use with escaping.', $class ), E_USER_NOTICE );
        }
        return addslashes( $string );
}

如上, 在 WordPress 上, 平台已经对此有所包装. 若自己写, 也也可以有所借鉴. 但若写 WP 插件还自己来轮子一下, 着实没什么必要.

Categories: Code

Yu

Ideals are like the stars: we never reach them, but like the mariners of the sea, we chart our course by them.

2 Comments

ghost · July 15, 2016 at 13:50

Google Chrome 51.0.2704.106 Google Chrome 51.0.2704.106 Windows 10 x64 Edition Windows 10 x64 Edition

注意看开发手册:
It will only escape values to be used in strings in the query. That is, it only provides escaping for values that will be within quotes in the SQL (as in field = ‘{$escaped_value}’). If your value is not going to be within quotes, your code will still be vulnerable to SQL injection.

还是应该尽量用$wpdb->prepare()

    yu · July 16, 2016 at 09:53

    Google Chrome 51.0.2704.103 Google Chrome 51.0.2704.103 Mac OS X  10.11.5 Mac OS X 10.11.5

    @ghost 学习了。

    这个是当时升级 PHP 后改别的插件时候用的,头痛医头那种….

Leave a Reply

Your email address will not be published.