文章目录:
thinkphp的db类
呵呵,这个简单。
因为,虽然Db.class.php中没有query()函数,但是继承它的‘Driver’下的所有数据库驱动类中都定义了query()函数,如:DbMysql.class.php中就定义了public function query($str)。
PHP中是允许父类调用子类中的函数的。
我自己写程序的时候也经常利用这个特性,结合构造函数,大大提高了程序的灵活性。
欢迎一起交流PHP技术。
求一个php写的DB类
这个是ECSHOP的数据库类,你可以参考一下:
class cls_mysql
{
var $link_id = NULL;
var $settings = array();
var $queryCount = 0;
var $queryTime = '';
var $queryLog = array();
var $max_cache_time = 300; // 最大的缓存时间,以秒为单位
var $cache_data_dir = 'temp/query_caches/';
var $root_path = '';
var $error_message = array();
var $platform = '';
var $version = '';
var $dbhash = '';
var $starttime = 0;
var $timeline = 0;
var $timezone = 0;
var $mysql_config_cache_file_time = 0;
var $mysql_disable_cache_tables = array(); // 不允许被缓存的表,遇到将不会进行缓存
function __construct($dbhost, $dbuser, $dbpw, $dbname = '', $charset = 'gbk', $pconnect = 0, $quiet = 0)
{
$this-cls_mysql($dbhost, $dbuser, $dbpw, $dbname, $charset, $pconnect, $quiet);
}
function cls_mysql($dbhost, $dbuser, $dbpw, $dbname = '', $charset = 'gbk', $pconnect = 0, $quiet = 0)
{
if (defined('EC_CHARSET'))
{
$charset = strtolower(str_replace('-', '', EC_CHARSET));
}
if (defined('ROOT_PATH') !$this-root_path)
{
$this-root_path = ROOT_PATH;
}
if ($quiet)
{
$this-connect($dbhost, $dbuser, $dbpw, $dbname, $charset, $pconnect, $quiet);
}
else
{
$this-settings = array(
'dbhost' = $dbhost,
'dbuser' = $dbuser,
'dbpw' = $dbpw,
'dbname' = $dbname,
'charset' = $charset,
'pconnect' = $pconnect
);
}
}
function connect($dbhost, $dbuser, $dbpw, $dbname = '', $charset = 'utf8', $pconnect = 0, $quiet = 0)
{
if ($pconnect)
{
if (!($this-link_id = @mysql_pconnect($dbhost, $dbuser, $dbpw)))
{
if (!$quiet)
{
$this-ErrorMsg("Can't pConnect MySQL Server($dbhost)!");
}
return false;
}
}
else
{
if (PHP_VERSION = '4.2')
{
$this-link_id = @mysql_connect($dbhost, $dbuser, $dbpw, true);
}
else
{
$this-link_id = @mysql_connect($dbhost, $dbuser, $dbpw);
mt_srand((double)microtime() * 1000000); // 对 PHP 4.2 以下的版本进行随机数函数的初始化工作
}
if (!$this-link_id)
{
if (!$quiet)
{
$this-ErrorMsg("Can't Connect MySQL Server($dbhost)!");
}
return false;
}
}
$this-dbhash = md5($this-root_path . $dbhost . $dbuser . $dbpw . $dbname);
$this-version = mysql_get_server_info($this-link_id);
/* 如果mysql 版本是 4.1+ 以上,需要对字符集进行初始化 */
if ($this-version '4.1')
{
if ($charset != 'latin1')
{
mysql_query("SET character_set_connection=$charset, character_set_results=$charset, character_set_client=binary", $this-link_id);
}
if ($this-version '5.0.1')
{
mysql_query("SET sql_mode=''", $this-link_id);
}
}
$sqlcache_config_file = $this-root_path . $this-cache_data_dir . 'sqlcache_config_file_' . $this-dbhash . '.php';
@include($sqlcache_config_file);
$this-starttime = time();
if ($this-max_cache_time $this-starttime $this-mysql_config_cache_file_time + $this-max_cache_time)
{
if ($dbhost != '.')
{
$result = mysql_query("SHOW VARIABLES LIKE 'basedir'", $this-link_id);
$row = mysql_fetch_assoc($result);
if (!empty($row['Value']{1}) $row['Value']{1} == ':' !empty($row['Value']{2}) $row['Value']{2} == "\\")
{
$this-platform = 'WINDOWS';
}
else
{
$this-platform = 'OTHER';
}
}
else
{
$this-platform = 'WINDOWS';
}
if ($this-platform == 'OTHER'
($dbhost != '.' strtolower($dbhost) != 'localhost:3306' $dbhost != '127.0.0.1:3306') ||
(PHP_VERSION = '5.1' date_default_timezone_get() == 'UTC'))
{
$result = mysql_query("SELECT UNIX_TIMESTAMP() AS timeline, UNIX_TIMESTAMP('" . date('Y-m-d H:i:s', $this-starttime) . "') AS timezone", $this-link_id);
$row = mysql_fetch_assoc($result);
if ($dbhost != '.' strtolower($dbhost) != 'localhost:3306' $dbhost != '127.0.0.1:3306')
{
$this-timeline = $this-starttime - $row['timeline'];
}
if (PHP_VERSION = '5.1' date_default_timezone_get() == 'UTC')
{
$this-timezone = $this-starttime - $row['timezone'];
}
}
$content = '' . "?php\r\n" .
'$this-mysql_config_cache_file_time = ' . $this-starttime . ";\r\n" .
'$this-timeline = ' . $this-timeline . ";\r\n" .
'$this-timezone = ' . $this-timezone . ";\r\n" .
'$this-platform = ' . "'" . $this-platform . "';\r\n?" . '';
@file_put_contents($sqlcache_config_file, $content);
}
/* 选择数据库 */
if ($dbname)
{
if (mysql_select_db($dbname, $this-link_id) === false )
{
if (!$quiet)
{
$this-ErrorMsg("Can't select MySQL database($dbname)!");
}
return false;
}
else
{
return true;
}
}
else
{
return true;
}
}
function select_database($dbname)
{
return mysql_select_db($dbname, $this-link_id);
}
function set_mysql_charset($charset)
{
/* 如果mysql 版本是 4.1+ 以上,需要对字符集进行初始化 */
if ($this-version '4.1')
{
if (in_array(strtolower($charset), array('gbk', 'big5', 'utf-8', 'utf8')))
{
$charset = str_replace('-', '', $charset);
}
if ($charset != 'latin1')
{
mysql_query("SET character_set_connection=$charset, character_set_results=$charset, character_set_client=binary", $this-link_id);
}
}
}
function fetch_array($query, $result_type = MYSQL_ASSOC)
{
return mysql_fetch_array($query, $result_type);
}
function query($sql, $type = '')
{
if ($this-link_id === NULL)
{
$this-connect($this-settings['dbhost'], $this-settings['dbuser'], $this-settings['dbpw'], $this-settings['dbname'], $this-settings['charset'], $this-settings['pconnect']);
$this-settings = array();
}
if ($this-queryCount++ = 99)
{
$this-queryLog[] = $sql;
}
if ($this-queryTime == '')
{
if (PHP_VERSION = '5.0.0')
{
$this-queryTime = microtime(true);
}
else
{
$this-queryTime = microtime();
}
}
/* 当当前的时间大于类初始化时间的时候,自动执行 ping 这个自动重新连接操作 */
if (PHP_VERSION = '4.3' time() $this-starttime + 1)
{
mysql_ping($this-link_id);
}
if (!($query = mysql_query($sql, $this-link_id)) $type != 'SILENT')
{
$this-error_message[]['message'] = 'MySQL Query Error';
$this-error_message[]['sql'] = $sql;
$this-error_message[]['error'] = mysql_error($this-link_id);
$this-error_message[]['errno'] = mysql_errno($this-link_id);
$this-ErrorMsg();
return false;
}
if (defined('DEBUG_MODE') (DEBUG_MODE 8) == 8)
{
$logfilename = $this-root_path . DATA_DIR . '/mysql_query_' . $this-dbhash . '_' . date('Y_m_d') . '.log';
$str = $sql . "\n\n";
if (PHP_VERSION = '5.0')
{
file_put_contents($logfilename, $str, FILE_APPEND);
}
else
{
$fp = @fopen($logfilename, 'ab+');
if ($fp)
{
fwrite($fp, $str);
fclose($fp);
}
}
}
return $query;
}
function affected_rows()
{
return mysql_affected_rows($this-link_id);
}
function error()
{
return mysql_error($this-link_id);
}
function errno()
{
return mysql_errno($this-link_id);
}
function result($query, $row)
{
return @mysql_result($query, $row);
}
function num_rows($query)
{
return mysql_num_rows($query);
}
function num_fields($query)
{
return mysql_num_fields($query);
}
function free_result($query)
{
return mysql_free_result($query);
}
function insert_id()
{
return mysql_insert_id($this-link_id);
}
function fetchRow($query)
{
return mysql_fetch_assoc($query);
}
function fetch_fields($query)
{
return mysql_fetch_field($query);
}
function version()
{
return $this-version;
}
function ping()
{
if (PHP_VERSION = '4.3')
{
return mysql_ping($this-link_id);
}
else
{
return false;
}
}
function escape_string($unescaped_string)
{
if (PHP_VERSION = '4.3')
{
return mysql_real_escape_string($unescaped_string);
}
else
{
return mysql_escape_string($unescaped_string);
}
}
function close()
{
return mysql_close($this-link_id);
}
function ErrorMsg($message = '', $sql = '')
{
if ($message)
{
echo "bECSHOP info/b: $message\n\nbr /br /";
//print('a href=";dberrno=2003dberror=Can%27t%20connect%20to%20MySQL%20server%20on" target="_blank";/a');
}
else
{
echo "bMySQL server error report:";
print_r($this-error_message);
//echo "br /br /a href=';dberrno=" . $this-error_message[3]['errno'] . "dberror=" . urlencode($this-error_message[2]['error']) . "' target='_blank';/a";
}
exit;
}
/* 仿真 Adodb 函数 */
function selectLimit($sql, $num, $start = 0)
{
if ($start == 0)
{
$sql .= ' LIMIT ' . $num;
}
else
{
$sql .= ' LIMIT ' . $start . ', ' . $num;
}
return $this-query($sql);
}
function getOne($sql, $limited = false)
{
if ($limited == true)
{
$sql = trim($sql . ' LIMIT 1');
}
$res = $this-query($sql);
if ($res !== false)
{
$row = mysql_fetch_row($res);
if ($row !== false)
{
return $row[0];
}
else
{
return '';
}
}
else
{
return false;
}
}
function getOneCached($sql, $cached = 'FILEFIRST')
{
$sql = trim($sql . ' LIMIT 1');
$cachefirst = ($cached == 'FILEFIRST' || ($cached == 'MYSQLFIRST' $this-platform != 'WINDOWS')) $this-max_cache_time;
if (!$cachefirst)
{
return $this-getOne($sql, true);
}
else
{
$result = $this-getSqlCacheData($sql, $cached);
if (empty($result['storecache']) == true)
{
return $result['data'];
}
}
$arr = $this-getOne($sql, true);
if ($arr !== false $cachefirst)
{
$this-setSqlCacheData($result, $arr);
}
return $arr;
}
如何实现thinkphp中Db类的方法调用风格?
我们先来看下官网对listen的说明:如果开启数据库的调试模式的话,你可以对数据库执行的任何SQL操作进行监听。这无疑很方便我们进行增删改查的调试,以及通过执行的时间进行有效的sql优化,
友情提示:数据库监听要写在执行sql语句的前面,因为只有在调用Db::listen之后的SQL语句才会被监听,调用之前的语句不会被监听。至于为什么我们后面讲!
使用如下方法:
123456
Db::listen(function($sql, $time, $explain){ // 记录SQL echo $sql. ' ['.$time.'s]'; // 查看性能分析结果 dump($explain);});
有很多小伙伴疑问该方法应该放在哪里?使用之后为什么没有效果,很可能就是提示上所说的那样了,那么接下来我们简单分析一下这个方法!
1、从Db::listen(),可以看出listen是Db中的一个静态方法,那么我们就去找db类
2、从Db类中没有找到该方法,但是我们从use think\db\Connection可以看出,引入了Connection类,我们在这个类找一下这个方法!
12345678910
/** * 监听SQL执行 * @access public * @param callable $callback 回调方法 * @return void */public function listen($callback){ self::$event[] = $callback;}
3、event 保存我们传入的回调方法
4、在看下面这2个方法
12345678910111213141516171819202122232425262728293031323334353637383940414243444546
/** * 数据库调试 记录当前SQL及分析性能 * @access protected * @param boolean $start 调试开始标记 true 开始 false 结束 * @param string $sql 执行的SQL语句 留空自动获取 * @return void */protected function debug($start, $sql = ''){ if (!empty($this-config['debug'])) { // 开启数据库调试模式 if ($start) { Debug::remark('queryStartTime', 'time'); } else { // 记录操作结束时间 Debug::remark('queryEndTime', 'time'); $runtime = Debug::getRangeTime('queryStartTime', 'queryEndTime'); $sql = $sql ?: $this-getLastsql(); $log = $sql . ' [ RunTime:' . $runtime . 's ]'; $result = []; // SQL性能分析 if ($this-config['sql_explain'] 0 === stripos(trim($sql), 'select')) { $result = $this-getExplain($sql); } // SQL监听 $this-trigger($sql, $runtime, $result); } }} protected function trigger($sql, $runtime, $explain = []){ if (!empty(self::$event)) { foreach (self::$event as $callback) { if (is_callable($callback)) { call_user_func_array($callback, [$sql, $runtime, $explain]); } } } else { // 未注册监听则记录到日志中 Log::record('[ SQL ] ' . $sql . ' [ RunTime:' . $runtime . 's ]', 'sql'); if (!empty($explain)) { Log::record('[ EXPLAIN : ' . var_export($explain, true) . ' ]', 'sql'); } }}
5、当我们执行了sql语句,就会触发会调用debug方法将执行日志写入日志文件中,同事调用trigger方法,如果我们最开始已经传入了回调方法,也就是
1
self::$event
不为空,(说明我们在执行sql语句之前就已经设置了监听)我们将调用我们的回调函数!
1
call_user_func_array
总结:在执行sql语句之前我们需要先设置监听,这就是为什么要把Db::listen()写在执行sql语句的前面!
下面我们来看下实际的效果:
1234567891011121314
public function expo(){ Db::listen(function($sql, $time, $explain){ // 记录SQL echo $sql. ' ['.$time.'s]'; // 查看性能分析结果 dump($explain); }); //Get data based on columns,执行sql语句 foreach($channel as $v) $list[$v['id']] = GetData::getData('news',"channel_id = {$v['id']} and status = 2",'id,title,author,create_time,channel_id,file_path','order_by desc','0,5'); return view('expo',[ 'list' = $list ]);}
效果图:
如何在PHP中阻止SQL注入?
【一、在服务器端配置】
安全,PHP代码编写是一方面,PHP的配置更是非常关键。
我们php手手工安装的,php的默认配置文件在 /usr/local/apache2/conf/php.ini,我们最主要就是要配置php.ini中的内容,让我们执行 php能够更安全。整个PHP中的安全设置主要是为了防止phpshell和SQL Injection的攻击,一下我们慢慢探讨。我们先使用任何编辑工具打开 /etc/local/apache2/conf/php.ini,如果你是采用其他方式安装,配置文件可能不在该目录。
(1) 打开php的安全模式
php的安全模式是个非常重要的内嵌的安全机制,能够控制一些php中的函数,比如system(),
同时把很多文件操作函数进行了权限控制,也不允许对某些关键文件的文件,比如/etc/passwd,
但是默认的php.ini是没有打开安全模式的,我们把它打开:
safe_mode = on
(2) 用户组安全
当safe_mode打开时,safe_mode_gid被关闭,那么php脚本能够对文件进行访问,而且相同
组的用户也能够对文件进行访问。
建议设置为:
safe_mode_gid = off
如果不进行设置,可能我们无法对我们服务器网站目录下的文件进行操作了,比如我们需要
对文件进行操作的时候。
(3) 安全模式下执行程序主目录
如果安全模式打开了,但是却是要执行某些程序的时候,可以指定要执行程序的主目录:
safe_mode_exec_dir = D:/usr/bin
一般情况下是不需要执行什么程序的,所以推荐不要执行系统程序目录,可以指向一个目录,
然后把需要执行的程序拷贝过去,比如:
safe_mode_exec_dir = D:/tmp/cmd
但是,我更推荐不要执行任何程序,那么就可以指向我们网页目录:
safe_mode_exec_dir = D:/usr/www
(4) 安全模式下包含文件
如果要在安全模式下包含某些公共文件,那么就修改一下选项:
safe_mode_include_dir = D:/usr/www/include/
其实一般php脚本中包含文件都是在程序自己已经写好了,这个可以根据具体需要设置。
(5) 控制php脚本能访问的目录
使用open_basedir选项能够控制PHP脚本只能访问指定的目录,这样能够避免PHP脚本访问
不应该访问的文件,一定程度上限制了phpshell的危害,我们一般可以设置为只能访问网站目录:
open_basedir = D:/usr/www
(6) 关闭危险函数
如果打开了安全模式,那么函数禁止是可以不需要的,但是我们为了安全还是考虑进去。比如,
我们觉得不希望执行包括system()等在那的能够执行命令的php函数,或者能够查看php信息的
phpinfo()等函数,那么我们就可以禁止它们:
disable_functions = system,passthru,exec,shell_exec,popen,phpinfo
如果你要禁止任何文件和目录的操作,那么可以关闭很多文件操作
disable_functions = chdir,chroot,dir,getcwd,opendir,readdir,scandir,fopen,unlink,delete,copy,mkdir, rmdir,rename,file,file_get_contents,fputs,fwrite,chgrp,chmod,chown
以上只是列了部分不叫常用的文件处理函数,你也可以把上面执行命令函数和这个函数结合,
就能够抵制大部分的phpshell了。
(7) 关闭PHP版本信息在http头中的泄漏
我们为了防止黑客获取服务器中php版本的信息,可以关闭该信息斜路在http头中:
expose_php = Off
比如黑客在 telnet 80 的时候,那么将无法看到PHP的信息。
(8) 关闭注册全局变量
在PHP中提交的变量,包括使用POST或者GET提交的变量,都将自动注册为全局变量,能够直接访问,
这是对服务器非常不安全的,所以我们不能让它注册为全局变量,就把注册全局变量选项关闭:
register_globals = Off
当然,如果这样设置了,那么获取对应变量的时候就要采用合理方式,比如获取GET提交的变量var,
那么就要用$_GET['var']来进行获取,这个php程序员要注意。
(9) 打开magic_quotes_gpc来防止SQL注入
SQL注入是非常危险的问题,小则网站后台被入侵,重则整个服务器沦陷,
所以一定要小心。php.ini中有一个设置:
magic_quotes_gpc = Off
这个默认是关闭的,如果它打开后将自动把用户提交对sql的查询进行转换,
比如把 ' 转为 \'等,这对防止sql注射有重大作用。所以我们推荐设置为:
magic_quotes_gpc = On
(10) 错误信息控制
一般php在没有连接到数据库或者其他情况下会有提示错误,一般错误信息中会包含php脚本当
前的路径信息或者查询的SQL语句等信息,这类信息提供给黑客后,是不安全的,所以一般服务器建议禁止错误提示:
display_errors = Off
如果你却是是要显示错误信息,一定要设置显示错误的级别,比如只显示警告以上的信息:
error_reporting = E_WARNING E_ERROR
当然,我还是建议关闭错误提示。
(11) 错误日志
建议在关闭display_errors后能够把错误信息记录下来,便于查找服务器运行的原因:
log_errors = On
同时也要设置错误日志存放的目录,建议根apache的日志存在一起:
error_log = D:/usr/local/apache2/logs/php_error.log
注意:给文件必须允许apache用户的和组具有写的权限。
MYSQL的降权运行
新建立一个用户比如mysqlstart
net user mysqlstart fuckmicrosoft /add
net localgroup users mysqlstart /del
不属于任何组
如果MYSQL装在d:\mysql ,那么,给 mysqlstart 完全控制 的权限
然后在系统服务中设置,MYSQL的服务属性,在登录属性当中,选择此用户 mysqlstart 然后输入密码,确定。
重新启动 MYSQL服务,然后MYSQL就运行在低权限下了。
如果是在windos平台下搭建的apache我们还需要注意一点,apache默认运行是system权限,
这很恐怖,这让人感觉很不爽.那我们就给apache降降权限吧。
net user apache fuckmicrosoft /add
net localgroup users apache /del
ok.我们建立了一个不属于任何组的用户apche。
我们打开计算机管理器,选服务,点apache服务的属性,我们选择log on,选择this account,我们填入上面所建立的账户和密码,
重启apache服务,ok,apache运行在低权限下了。
实际上我们还可以通过设置各个文件夹的权限,来让apache用户只能执行我们想让它能干的事情,给每一个目录建立一个单独能读写的用户。
这也是当前很多虚拟主机提供商的流行配置方法哦,不过这种方法用于防止这里就显的有点大材小用了。
【二、在PHP代码编写】
虽然国内很多PHP程序员仍在依靠addslashes防止SQL注入,还是建议大家加强中文防止SQL注入的检查。addslashes的问题在于黑客可以用0xbf27来代替单引号,而addslashes只是将0xbf27修改为0xbf5c27,成为一个有效的多字节字符,其中的0xbf5c仍会被看作是单引号,所以addslashes无法成功拦截。
当然addslashes也不是毫无用处,它是用于单字节字符串的处理,多字节字符还是用mysql_real_escape_string吧。
另外对于php手册中get_magic_quotes_gpc的举例:
if (!get_magic_quotes_gpc()) {
$lastname = addslashes($_POST[‘lastname’]);
} else {
$lastname = $_POST[‘lastname’];
}
最好对magic_quotes_gpc已经开放的情况下,还是对$_POST[’lastname’]进行检查一下。
再说下mysql_real_escape_string和mysql_escape_string这2个函数的区别:
mysql_real_escape_string 必须在(PHP 4 = 4.3.0, PHP 5)的情况下才能使用。否则只能用 mysql_escape_string ,两者的区别是:mysql_real_escape_string 考虑到连接的
当前字符集,而mysql_escape_string 不考虑。
总结一下:
* addslashes() 是强行加\;
* mysql_real_escape_string() 会判断字符集,但是对PHP版本有要求;
* mysql_escape_string不考虑连接的当前字符集。
-------------------------------------------------------------------------------------------------
在PHP编码的时候,如果考虑到一些比较基本的安全问题,首先一点:
1. 初始化你的变量
为什么这么说呢?我们看下面的代码:
PHP代码
?php
if ($admin)
{
echo '登陆成功!';
include('admin.php');
}
else
{
echo '你不是管理员,无法进行管理!';
}
?
好,我们看上面的代码好像是能正常运行,没有问题,那么加入我提交一个非法的参数过去呢,那么效果会如何呢?比如我们的这个页是,那么我们提交:,呵呵,你想一些,我们是不是直接就是管理员了,直接进行管理。
当然,可能我们不会犯这么简单错的错误,那么一些很隐秘的错误也可能导致这个问题,比如phpwind论坛有个漏洞,导致能够直接拿到管理员权限,就是因为有个$skin变量没有初始化,导致了后面一系列问题。那么我们如何避免上面的问题呢?首先,从php.ini入手,把php.ini里面的register_global =off,就是不是所有的注册变量为全局,那么就能避免了。但是,我们不是服务器管理员,只能从代码上改进了,那么我们如何改进上面的代码呢?我们改写如下:
PHP代码
?php
$admin = 0; // 初始化变量
if ($_POST['admin_user'] $_POST['admin_pass'])
{
// 判断提交的管理员用户名和密码是不是对的相应的处理代码
// ...
$admin = 1;
}
else
{
$admin = 0;
}
if ($admin)
{
echo '登陆成功!';
include('admin.php');
}
else
{
echo '你不是管理员,无法进行管理!';
}
?
那么这时候你再提交就不好使了,因为我们在一开始就把变量初始化为 $admin = 0 了,那么你就无法通过这个漏洞获取管理员权限。
2. 防止SQL Injection (sql注射)
SQL 注射应该是目前程序危害最大的了,包括最早从asp到php,基本上都是国内这两年流行的技术,基本原理就是通过对提交变量的不过滤形成注入点然后使恶意用户能够提交一些sql查询语句,导致重要数据被窃取、数据丢失或者损坏,或者被入侵到后台管理。
那么我们既然了解了基本的注射入侵的方式,那么我们如何去防范呢?这个就应该我们从代码去入手了。
我们知道Web上提交数据有两种方式,一种是get、一种是post,那么很多常见的sql注射就是从get方式入手的,而且注射的语句里面一定是包含一些sql语句的,因为没有sql语句,那么如何进行,sql语句有四大句:select 、update、delete、insert,那么我们如果在我们提交的数据中进行过滤是不是能够避免这些问题呢?
于是我们使用正则就构建如下函数:
PHP代码
?php
function inject_check($sql_str)
{
return eregi('select|insert|update|delete|'|
function verify_id($id=null)
{
if (!$id) { exit('没有提交参数!'); } // 是否为空判断
elseif (inject_check($id)) { exit('提交的参数非法!'); } // 注射判断
elseif (!is_numeric($id)) { exit('提交的参数非法!'); } // 数字判断
$id = intval($id); // 整型化
return $id;
}
?
呵呵,那么我们就能够进行校验了,于是我们上面的程序代码就变成了下面的:
PHP代码
?php
if (inject_check($_GET['id']))
{
exit('你提交的数据非法,请检查后重新提交!');
}
else
{
$id = verify_id($_GET['id']); // 这里引用了我们的过滤函数,对$id进行过滤
echo '提交的数据合法,请继续!';
}
?
好,问题到这里似乎都解决了,但是我们有没有考虑过post提交的数据,大批量的数据呢?
比如一些字符可能会对数据库造成危害,比如 ' _ ', ' %',这些字符都有特殊意义,那么我们如果进行控制呢?还有一点,就是当我们的php.ini里面的magic_quotes_gpc = off的时候,那么提交的不符合数据库规则的数据都是不会自动在前面加' '的,那么我们要控制这些问题,于是构建如下函数:
PHP代码
?php
function str_check( $str )
{
if (!get_magic_quotes_gpc()) // 判断magic_quotes_gpc是否打开
{
$str = addslashes($str); // 进行过滤
}
$str = str_replace("_", "\_", $str); // 把 '_'过滤掉
$str = str_replace("%", "\%", $str); // 把' % '过滤掉
return $str;
}
?
我们又一次的避免了服务器被沦陷的危险。
最后,再考虑提交一些大批量数据的情况,比如发贴,或者写文章、新闻,我们需要一些函数来帮我们过滤和进行转换,再上面函数的基础上,我们构建如下函数:
PHP代码
?php
function post_check($post)
{
if (!get_magic_quotes_gpc()) // 判断magic_quotes_gpc是否为打开
{
$post = addslashes($post); // 进行magic_quotes_gpc没有打开的情况对提交数据的过滤
}
$post = str_replace("_", "\_", $post); // 把 '_'过滤掉
$post = str_replace("%", "\%", $post); // 把' % '过滤掉
$post = nl2br($post); // 回车转换
$post= htmlspecialchars($post); // html标记转换
return $post;
}
?
呵呵,基本到这里,我们把一些情况都说了一遍,其实我觉得自己讲的东西还很少,至少我才只讲了两方面,再整个安全中是很少的内容了,考虑下一次讲更多,包括php安全配置,apache安全等等,让我们的安全正的是一个整体,作到最安全。
最后在告诉你上面表达的:1. 初始化你的变量 2. 一定记得要过滤你的变量
PHP db类的使用
你的query()有返回值,你可以把代码改成这样再试试
function fn_select($tabl){
return $this-query("select * from $tabl order by id desc");
}
你没有用到自己定义的
function fetch_array($query, $result_type = MYSQL_ASSOC) {
return @mysql_fetch_array($query, $result_type);
}
你试着在后面加上
$row=$db-fetch_array($a,MYSQL_NUM);
print_r($row);
应该就看到结果了
365PHP培训与交流平台 欢迎光临
if (PHP_VERSION = '4.3') { return mysql_real_escape_string($unescaped_string); } else {
s-getLastsql(); $log = $sql . ' [ RunTime:' . $runtime . 's ]';
($result, $arr); } return $arr;}如何实现thinkphp中Db类的方法调用风格?我们先来看下官网对listen的说明:如果开启数据库的调试模式的话,你可以对数据库执行的任何SQL操作进行监听。这无疑很方便我们进行增删改查的调试,以及通过执行的时间进行有
} // SQL监听 $this-trigger($sql, $runtime, $result); } }} protected function trigger($sq