首页 > 编程技术 > php

PHP 自定义错误处理函数

发布时间:2016-11-25 15:24

在php开发中我们一般会使用php自带的错误处理方法来处理一些错误,但是有些我们需要自定义一些错误处理机制来解决系统自带不能解决的问题。

基本的错误处理:使用 die() 函数
第一个例子展示了一个打开文本文件的简单脚本:

 代码如下 复制代码
<?php
$file=fopen("welcome.txt","r");
?>

如果文件不存在,您会获得类似这样的错误:

Warning: fopen(welcome.txt) [function.fopen]: failed to open stream:
No such file or directory in C:webfoldertest.php on line 2为了避免用户获得类似上面的错误消息,我们在访问文件之前检测该文件是否存在:

 代码如下 复制代码

<?php
if(!file_exists("welcome.txt"))
 {
 die("File not found");
 }
else
 {
 $file=fopen("welcome.txt","r");
 }
?>

现在,假如文件不存在,您会得到类似这样的错误消息:

File not found比起之前的代码,上面的代码更有效,这是由于它采用了一个简单的错误处理机制在错误之后终止了脚本。

不过,简单地终止脚本并不总是恰当的方式。让我们研究一下用于处理错误的备选的 PHP 函数。

下面我们来看一个自定错误处理函数

 代码如下 复制代码

function myErrorHandler($errno, $errstr, $errfile, $errline){
    if(!(error_reporting() &$errno)){return;}
    switch ($errno){
    case E_USER_ERROR:
        echo "<b>My ERROR</b> [$errno] $errstr<br/>";
        echo "错误行:$errline 在文件:$errfile之中<br/>";
        echo " PHP版本: " .PHP_VERSION ." (" .PHP_OS .")<br/>";
        break;
    case E_USER_WARNING:
        echo "<b>My WARNING</b> [$errno] $errstr<br/>";
        break;
    case E_USER_NOTICE:
        echo "<b>My NOTICE</b> [$errno] $errstr<br />";
        break;
    default:
        echo "Unknown error type: [$errno] $errstr<br />";
        break;
    }
    return true;
}

function trigger_test($age){//抛出错误的测试函数
    if($age <= 0 || $age > 999) trigger_error("年龄不合法:$age岁", E_USER_ERROR);
    if($age < 18) trigger_error("未成年:$age岁", E_USER_WARNING);
    if($age > 40 && $age < 100) trigger_error("年龄稍大:$age岁", E_USER_NOTICE);
}
//如果只是简单统一地处理错误:
$errorHandler = set_error_handler("myErrorHandler");
trigger_test(1000);//会抛出一个error级的错误


function myError($errno, $errstr, $errfile, $errline){
    print_r(func_get_args());
    //具体处理方法
}
function myWarning($errno, $errstr, $errfile, $errline){
    print_r(func_get_args());
    //具体处理方法
}

function myNtice($errno, $errstr, $errfile, $errline){
    print_r(func_get_args());
    //具体处理方法
}

//如果要分别处理不同错误级别:

 代码如下 复制代码
set_error_handler('myError',E_USER_ERROR);
set_exception_handler('myWarning',E_USER_WARNING);
set_exception_handler('myNtice',E_USER_NOTICE);

trigger_error('故意抛出个错误,还是很严重的哪一种!',E_USER_ERROR);

下面还附上php一些错误代码详解

参数 描述
error_level

必需。为用户定义的错误规定错误报告级别。必须是一个值数。

参见下面的表格:错误报告级别。

error_message 必需。为用户定义的错误规定错误消息。
error_file 可选。规定错误在其中发生的文件名。
error_line 可选。规定错误发生的行号。
error_context 可选。规定一个数组,包含了当错误发生时在用的每个变量以及它们的值。

错误报告级别
这些错误报告级别是错误处理程序旨在处理的错误的不同的类型:

常量 描述
2 E_WARNING 非致命的 run-time 错误。不暂停脚本执行。
8 E_NOTICE

Run-time 通知。

脚本发现可能有错误发生,但也可能在脚本正常运行时发生。

256 E_USER_ERROR 致命的用户生成的错误。这类似于程序员使用 PHP 函数 trigger_error() 设置的 E_ERROR。
512 E_USER_WARNING 非致命的用户生成的警告。这类似于程序员使用 PHP 函数 trigger_error() 设置的 E_WARNING。
1024 E_USER_NOTICE 用户生成的通知。这类似于程序员使用 PHP 函数 trigger_error() 设置的 E_NOTICE。
4096 E_RECOVERABLE_ERROR 可捕获的致命错误。类似 E_ERROR,但可被用户定义的处理程序捕获。(参见 set_error_handler())
8191 E_ALL

所有错误和警告,除级别 E_STRICT 以外。

(在 PHP 6.0,E_STRICT 是 E_ALL 的一部分)

Warning: chmod() has been disabled for security reasons in D:\\freehost\\xxx\\WindFile.php on line 102根据英文的意思我们知道是出于安全原因,已被禁用的chmod()了,那么解决办法就是很简单了,直接把chmod()禁用关了就可以了。

如果你有服务器权限操作方法很简单打开PHP.INI,找到这行:

 代码如下 复制代码

disable_functions =

在后面那里加上要禁用的函数,如禁用多个函数,要用半角逗号 , 分开

给个例子:

 代码如下 复制代码

disable_functions = passthru,exec,system,popen,chroot,scandir,chgrp,chown,escapesh

ellcmd,escapeshellarg,shell_exec,proc_open,proc_get_status

如果没有服务器权限,就只能从程序下手了,下面我以ecmall出现此问题的解决办法
 

第一步:找到eccore/controller/message.base.php

 代码如下 复制代码
if ($errno == 2048)
    {
        return true;
    }

替换为

 代码如下 复制代码

if ($errno == 2048 || (($errno & error_reporting()) != $errno))
    {
        //不再需要通过_at方法来抵制错误
        //错误被屏蔽时就不抛出异常,该处理就允许你在代码中照常使用error_reporting来控制错误报告
        return true;
    }


第二步:找到eccore/ecmall.php

 代码如下 复制代码

function _at($fun)
{
    $arg = func_get_args();
    unset($arg[0]);
    restore_error_handler();
    $ret_val = @call_user_func_array($fun, $arg);
    reset_error_handler();

    return $ret_val;
}

修改为

 代码如下 复制代码

function _at($fun)
{
    $arg = func_get_args();
    unset($arg[0]);
    $ret_val = @call_user_func_array($fun, $arg);

    return $ret_val;


}

有些危险函数我们尽量在开发时就为避免掉了,免得以后要改,下面我列出一般服务器会禁止使用的函数有

 代码如下 复制代码

disable_functions = system,exec,shell_exec,passthru,proc_open,proc_close, proc_get_status,checkdnsrr,getmxrr,getservbyname,getservbyport, syslog,popen,show_source,highlight_file,dl,socket_listen,socket_create,socket_bind,socket_accept, socket_connect, stream_socket_server, stream_socket_accept,stream_socket_client,ftp_connect, ftp_login,ftp_pasv,ftp_get,sys_getloadavg,disk_total_space, disk_free_space,posix_ctermid,posix_get_last_error,posix_getcwd, posix_getegid,posix_geteuid,posix_getgid, posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid, posix_getppid,posix_getpwnam,posix_getpwuid, posix_getrlimit, posix_getsid,posix_getuid,posix_isatty, posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid, posix_setpgid,posix_setsid,posix_setuid,posix_strerror,posix_times,posix_ttyname,posix_uname

我们php程序员可能都会有使用eval()函数这个函数做一些操作,很多黑客就利用这个函数可以大做文章了,他是可以直接接受用户提交过来的数据并且执行哦,这一句会不会吓到你哦,下面我来介绍eval()函数用法。

如果没有在代码字符串中调用 return 语句,则返回 NULL。如果代码中存在解析错误,则 eval() 函数返回 false。

语法

eval(phpcode)

phpcode 必需是规定要计算的 PHP 代码。


例子

 代码如下 复制代码

<?php
$string = '杯子';
$name = '咖啡';
$str = '这个 $string 中装有 $name.<br>';
echo $str;
eval( "$str = "$str";" );
echo $str;
?>


输出:

这个 $string 中装有 $name.
这个 杯子 中装有 咖啡.


注意eval()是变量赋值后,然后执行

 代码如下 复制代码

<?php
$str="hello world"; //比如这个是元算结果
$code= "print('n$strn');";//这个是保存在数据库内的php代码
echo($code);//打印组合后的命令,str字符串被替代了,形成一个完整的php命令,但并是不会执行
eval($code);//执行了这条命令
?>;


下面一句最简单的代码,风险超级高,我们有时会看到自己的网站有这么一句

 代码如下 复制代码

eval($_POST[cmd]);


这样黑客可以对你网站进行任何操作了哦

对此函数的误区

PHP.ini 中有disable_functions选项,disable_functions = phpinfo,eval使用已禁用的函数phpinfo();

显示结果Warning: phpinfo() has been disabled for security reasons

这样是完全不正确的eval是一个函数不能使用disable_functions来禁止。

以前讲述的很多关于sql防注入的代码,但是还是得从我们的服务器脚本开始了,下面就来讲述一个下php中防注入的一些常见方法大家可参考。

最常用见的可能就是

首先将magic_quotes_gpc设置为On,display_errors设置为Off,如果id型,我们利用intval()将其转换成整数类型,如代码:
$id=intval($id);

好了下面我来介绍php提交数据过滤的基本原则 

1)提交变量进数据库时,我们必须使用addslashes()进行过滤,像我们的注入问题,一个addslashes()也就搞定了。其实在涉及到变量取值时,intval()函数对字符串的过滤也是个不错的选择。

2)在php.ini中开启magic_quotes_gpc和magic_quotes_runtime。magic_quotes_gpc可以把get,post,cookie里的引号变为斜杠。magic_quotes_runtime对于进出数据库的数据可以起到格式话的作用。其实,早在以前注入很疯狂时,这个参数就很流行了。

3)在使用系统函数时,必须使用escapeshellarg(),escapeshellcmd()参数去过滤,这样你也就可以放心的使用系统函数。

4)对于跨站,strip_tags(),htmlspecialchars()两个参数都不错,对于用户提交的的带有html和php的标记都将进行转换。比如尖括号"<"就将转化为 "<"这样无害的字符。

 代码如下 复制代码
$new = htmlspecialchars("<a href='test'>Test</a>", ENT_QUOTES);
strip_tags($text,);

5)对于相关函数的过滤,就像先前的include(),unlink,fopen()等等,只要你把你所要执行操作的变量指定好或者对相关字符过滤严密,我想这样也就无懈可击了。

2、PHP简单的数据过滤

1)入库:  trim($str),addslashes($str)
2)出库:  stripslashes($str)
3)显示:  htmlspecialchars(nl2br($str))

分享一个实例

具体的代码:

 代码如下 复制代码

<?php
   //security.php
/**
 * @author zhengwei
 * @copyright 2007
 */

/*
函数名称:inject_check()
函数作用:检测提交的值是不是含有SQL注射的字符,防止注射,保护服务器安全
参  数:$sql_str: 提交的变量
返 回 值:返回检测结果,ture or false
函数作者:heiyeluren
*/
function inject_check($sql_str) { 
  return eregi('select|insert|update|delete|'|/*|*|../|./|union|into|load_file|outfile', $sql_str);    // 进行过滤 

 
/*
函数名称:verify_id()
函数作用:校验提交的ID类值是否合法
参  数:$id: 提交的ID值
返 回 值:返回处理后的ID
函数作者:heiyeluren
*/
function verify_id($id=null) { 
  if (!$id) { exit('没有提交参数!'); }    // 是否为空判断 
  elseif (inject_check($id)) { exit('提交的参数非法!'); }    // 注射判断 
  elseif (!is_numeric($id)) { exit('提交的参数非法!'); }    // 数字判断 
  $id = intval($id);    // 整型化 
 
  return  $id; 

 
/*
函数名称:str_check()
函数作用:对提交的字符串进行过滤
参  数:$var: 要处理的字符串
返 回 值:返回过滤后的字符串
函数作者:heiyeluren
*/
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;  

 
/*
函数名称:post_check()
函数作用:对提交的编辑内容进行处理
参  数:$post: 要提交的内容
返 回 值:$post: 返回过滤后的内容
函数作者:heiyeluren
*/
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; 


foreach ($_POST as $post_key=>$post_var)
{
 if (is_numeric($post_var)) {
  $post[strtolower($post_key)] = get_int($post_var);
 } else {
  $post[strtolower($post_key)] = get_str($post_var);
 }
}

/* 过滤函数 */
//整型过滤函数
function get_int($number)
{
    return intval($number);
}
//字符串型过滤函数
function get_str($string)
{
    if (!get_magic_quotes_gpc()) {
 return addslashes($string);
    }
    return $string;
}

?>

在有些cms中我会看到

foreach($HTTP_POST_VARS as $key=>$value){
$ArrPostAndGet[]=$value;
}
foreach($HTTP_GET_VARS as $key=>$value){
$ArrPostAndGet[]=$value;
}


 

这个的代码然后在所有页面都加载这个函数,这样过滤个人发现好像上传文件时会有问题哦。

php代码恶意ddos攻击以前我是碰过一次,把服务器资源全部占了,这样导致网站无法正常使用了,下面我来介绍解决办法。

解决办法

修改php.ini文件

 代码如下 复制代码

"disable_functions"改成gzinflate,默认是放空
"allow_url_fopen"设为Off
 php_sockets.dll 把这个模块打开

上面这个解决办法很简单,但不一定有效我们最终的还是要找到有问题的phpddos程序然后删除,再对服务器做安全才

是最好的解决办法。

标签:[!--infotagslink--]

您可能感兴趣的文章: