PHP验证码生成程序几种方法

 更新时间:2016年11月25日 15:23  点击:2353
PHP验证码生这个功能常用于用用户注册登录或发布信息时一个安全验证的基本功能,下面小编来给大家介绍一些常用的PHP验证码生成代码与应用实例。

例1,直接使用数组,此方法比较简单

 代码如下 复制代码

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<?php

$arr=array(2,3,4,5,8,1,9,7,"a","b","c","d","e","f","中","国","南","北","大","小","多","少");
$b=array_rand($arr,3);

?>
<form action="yz.php" method="post">
<input type="text" name="code" />
<input type="hidden" name="yanzhengma" value="<?php foreach($b  as $key)
         {
          echo $arr[$key];
         }
       ?>"
/>

<input type="submit" name="submit" value="do" />
</form>
<?php

echo “code:";
foreach($b  as $key)
{
 echo $arr[$key];
}
?>

</body>
</html>(以上语句另存为一个php文件)

<?php
header(“Content-Type:text/html;charset=utf-8");
echo $_POST["yanzhengma"];
echo $_POST["code"];
if($_POST["yanzhengma"]==$_POST["code"])
{
 echo “验证码正确";
}
else
{
 die(“<script>alert(‘验证码不正确");location="array_rand.php";</script>");
}
?>

(以上语句另存为yz.php)


例2,也是用数组只不是数据多了一点

 代码如下 复制代码

function UPCAbarcode($code) {
  $lw = 2; $hi = 100;
  $Lencode = array('0001101','0011001','0010011','0111101','0100011',
                   '0110001','0101111','0111011','0110111','0001011');
  $Rencode = array('1110010','1100110','1101100','1000010','1011100',
                   '1001110','1010000','1000100','1001000','1110100');
  $ends = '101'; $center = '01010';
  /* UPC-A Must be 11 digits, we compute the checksum. */
  if ( strlen($code) != 11 ) { die("UPC-A Must be 11 digits."); }
  /* Compute the EAN-13 Checksum digit */
  $ncode = '0'.$code;
  $even = 0; $odd = 0;
  for ($x=0;$x<12;$x++) {
    if ($x % 2) { $odd += $ncode[$x]; } else { $even += $ncode[$x]; }
  }
  $code.=(10 - (($odd * 3 + $even) % 10)) % 10;
  /* Create the bar encoding using a binary string */
  $bars=$ends;
  $bars.=$Lencode[$code[0]];
  for($x=1;$x<6;$x++) {
    $bars.=$Lencode[$code[$x]];
  }
  $bars.=$center;
  for($x=6;$x<12;$x++) {
    $bars.=$Rencode[$code[$x]];
  }
  $bars.=$ends;
  /* Generate the Barcode Image */
  $img = ImageCreate($lw*95+30,$hi+30);
  $fg = ImageColorAllocate($img, 0, 0, 0);
  $bg = ImageColorAllocate($img, 255, 255, 255);
  ImageFilledRectangle($img, 0, 0, $lw*95+30, $hi+30, $bg);
  $shift=10;
  for ($x=0;$x    if (($x<10) || ($x>=45 && $x<50) || ($x >=85)) { $sh=10; } else { $sh=0; }
    if ($bars[$x] == '1') { $color = $fg; } else { $color = $bg; }
    ImageFilledRectangle($img, ($x*$lw)+15,5,($x+1)*$lw+14,$hi+5+$sh,$color);
  }
  /* Add the Human Readable Label */
  ImageString($img,4,5,$hi-5,$code[0],$fg);
  for ($x=0;$x<5;$x++) {
    ImageString($img,5,$lw*(13+$x*6)+15,$hi+5,$code[$x+1],$fg);
    ImageString($img,5,$lw*(53+$x*6)+15,$hi+5,$code[$x+6],$fg);
  }
  ImageString($img,4,$lw*95+17,$hi-5,$code[11],$fg);
  /* Output the Header and Content. */
  header("Content-Type: image/png");
  ImagePNG($img);
}

UPCAbarcode('12345678901');

?>

例3,这个是一个比较完整的ajax刷新验证码实例


vcode.php

 代码如下 复制代码

<?php 
session_start();//开启session功能
header("Cache-Control: no-cache, must-revalidate");

$im = imagecreate(60,30);//定义图片宽度和高度
$vcode=getVCode();//获取要显示的字符
$bg = imagecolorallocate($im, 255, 255, 255);//定义图片背景
$txt = imagecolorallocate($im, rand(0,255), rand(0,255), rand(0,255));//定义要显示字符的颜色
imagestring($im, 8, 0, 0, $vcode, $txt);//写入字符串到图片
header(Content-type: image/jpeg);//定义Content-type
imagejpeg($im);//以JPEG格式显示图片
$_SESSION[vcode]=$vcode;//写入SESSION
 
function getVCode(){    //随机生成用户指定个数的字符串
  $codenum=4;
  $checkcode="";
  $string="";//要显示的可选字符串,请自行定义;
  for($i=0;$i<$codenum;$i  ) {  
  $number=rand(0,2);  
  switch($number){  //根据可选字符串可灵活定义;
       case 0 : $rand_number=rand(0,10);break;   
       case 1 : $rand_number=rand(11,36);break;  
       case 2 : $rand_number=rand(37,62);break;  
  }  
  $code=substr($string,$rand_number,1);
  $checkcode=$checkcode.$code;  
  } 
  return  $checkcode;
}     
?>


loginform.html

 代码如下 复制代码


<!--详细信息-->
<form name="loginform">
<table class="dtable">
        <tr>
          <td width="100"> 用户名 </td><td><input class="txtbox" name="loginname" type=text size="30"/></td>
        </tr>
        <tr>
          <td width="100"> 密码 </td><td><input class="txtbox" name="loginpwd" type=password size="30"/></td>
        </tr>
        <tr>
          <td width="100"> 验证码 </td>
          <td><input class="txtbox" name="loginvcode" type=text size="10"/>
          <img id="vcode" src="vcode.php" alt="验证码" align="absmiddle"/>
          <a href="javascript:getVCode();">换一张</a></td>
        </tr>
</table>
<table>
        <tr><td colspan="2">
          <input class="btn" name="ok" type="button" value="登录" onclick="setType('usr');usrVCode();">
          <input class="btn" name="reset" type="reset" value="重写">
          <input class="btn" name="exit" type="button" value="退出" onclick="Hide();">
        </td></tr>
</table>
<table>
        <tr><td colspan="2">
          还没有注册? <a href="javascript:setType('usr');Show('0','addform');">马上注册</a>
          忘记密码? <a href="javascript:setType('usr');Show('0','pwdform');">取回密码</a>
        </td></tr>
</table>
</form>

vcode.js

 代码如下 复制代码

//该函数用来获取验证码

function getVCode() {
        var vcode=document.getElementById('vcode');
        vcode.src = 'vcode.php?nocache='+new Date().getTime();
}

//该函数用来验证验证码
function usrVCode() {
        if(!checkLogin())return false;
        var loginvcode=document.loginform.loginvcode.value;
        var xmlhttp1=createAjax();
        var data='&loginvcode='+loginvcode;
if (xmlhttp1) {
  var state=document.getElementById('state');
          xmlhttp1.open('get',?do=vcodedo'+data,true);
  xmlhttp1.send(null);
  xmlhttp1.onreadystatechange=function() {
    if (xmlhttp1.readyState==4 && xmlhttp1.status==200) {
             setTimeout("state.style.display = 'none';",1000);
     var myres=xmlhttp1.responseText;
             var result=(myres==1)?"恭喜您,验证码输入正确!":"很抱歉,验证码输入错误!";
             if(myres==0)alert(result);
             if(myres==1)usrLogin();
            }
    else {
             state.style.display = "";
     state.style.left=(document.body.offsetWidth-350)/2;
             state.style.top=(document.body.offsetHeight-235)/2+document.body.scrollTop;
    }
          }
}
}

在php中open_basedir是php中一个用得不多的函数,但是open_basedir函数一不小心就给人家给进入你服务器了,open_basedir到底有多神奇我们来看看吧。

先看一段我们不考虑open_basedir安全问题代码

在php写了句require_once ‘../Zend/Loader.php’; 报错:
Warning: require_once() [function.require-once]: open_basedir restriction in effect. File(../Zend/Loader.php) is not within the allowed path(s): (D:/phpnow/vhosts/zf.com;C:/Windows/Temp;) in D:/phpnow/vhosts/zf.com/index.php on line 6

Warning: require_once(../Zend/Loader.php) [function.require-once]: failed to open stream: Operation not permitted in D:/phpnow/vhosts/zf.com/index.php on line 6

Fatal error: require_once() [function.require]: Failed opening required '../Zend/Loader.php' (include_path='D:/phpnow/vhosts/zf.comZend;.;C:/php5/pear') in D:/phpnow/vhosts/zf.com/index.php on line 6字面分析是受到了open_basedir的限制,造成Operation not permitted(操作不被允许)。


打开php.ini跳转到open_basedir相关设置段落:

; open_basedir, if set, limits all file operations to the defined directory
; and below.  This directive makes most sense if used in a per-directory
; or per-virtualhost web server configuration file. This directive is
; *NOT* affected by whether Safe Mode is turned On or Off.

;open_basedir =如果设置了open_basedir,那么所有能被操作的文件就只能限制在open_basedir指定的目录里面。 这个在虚拟主机里面这个指令相当有用。不管安全模式是否打开,这个指令都不受影响。 看来php.ini没有设置open_basedir。 打开apache虚拟主机配置文件:

 代码如下 复制代码

<virtualhost *>
    <directory "../vhosts/zf.com">
        Options -Indexes FollowSymLinks
    </directory>
    ServerAdmin admin@zf.com
    DocumentRoot "../vhosts/zf.com"
    ServerName zf.com:80
    ServerAlias *.zf.com
    ErrorLog logs/zf.com-error_log
    php_admin_value open_basedir "D:/phpnow/vhosts/zf.com;C:/Windows/Temp;"
</virtualhost>

里面的php_admin_value open_basedir就限定了操作目录。我这里是本地测试,安全因素不考虑,直接将 php_admin_value open_basedir “D:/phpnow/vhosts/zf.com;C:/Windows/Temp;” 删除掉,重新启动apache,

上面如果给利用完可以可随意删除服务器文件了,但是比较幸运的是目前php站点的安全配置基本是open_basedir+safemode,确实很无敌、很安全,即使在权限没有很好设置的环境中,这样配置都是相当安全的,当然了,不考虑某些可以绕过的情况。本文讨论两点开启open_basedir后可能导致的安全隐患(现实遇到的),一个也许属于php的一个小bug,另外一个可能是由于配置不当产生的。

一、open_basedir中处理文件路径时没有严格考虑目录的存在,这将导致本地包含或者本地文件读取的绕过。

看一个本地文件任意读取的例子:

 代码如下 复制代码
<?php
$file = $_GET['file'];
preg_match("/^img/", $file) or die('error_file');
$file='/home/www/upload/'.$file;
file_exists($file) or die('no_such_file');
$f = fopen("$file", 'r');
$jpeg = fread($f, filesize("$file"));
fclose($f);
Header("Content-type: image/jpeg");
Header("Content-disposition: inline; filename=test.jpg");
echo $jpeg;
?>

虽然file是任意提交的,但是限制了前缀必须为img,我们如果想跳出目录读文件,比如,读取网站根目录下的config.php,我们得提交?file=img/../../config.php,但是此处有个限制条件,就是upload目录下不存在img文件夹,在windows文件系统里,系统不会去考虑目录存在不存在,会直接跳转目录从而导致漏洞;但linux文件系统非常严谨,它会仔细判断每一层目录是否存在,比如这里由于不存在img,则跳出去读取文件的时候直接报错。看如下一个示意图:


再看一个类似的本地包含的例子:

 代码如下 复制代码
<?php
include "aaa".$_GET['lang'].".php";
?>

由于linux文件系统的限制,我们无法利用旁注去包含tmp下的文件。

linux严谨的考虑在php那里显然没有得到深刻的体会。在开启了open_basedir的时候,php对传入的文件路径进行了取真实路径的处理,然后跟open_basedir中设置的路径进行比较:

 代码如下 复制代码

……
/* normalize and expand path */
if (expand_filepath(path, resolved_name TSRMLS_CC) == NULL) {
return -1;
}

path_len = strlen(resolved_name);
memcpy(path_tmp, resolved_name, path_len + 1); /* safe */
……

但php在处理的时候忽略了检查路径是否存在,于是在开启了open_basedir时,上面那个文件读取的例子,我们可以使用?file=img/../../config.php来直接读取了,此时提交的路径已经被处理成/home/www/config.php了,所以不存在任何读取问题了。

问题由渗透测试的时候遇到绕过的情况从而导致疑问,经分析环境差异,然后xi4oyu牛指点有可能是open_basedir的问题后测试总结出这是php的一个小的bug,但是很有可能导致安全隐患。

二、open_basedir的值配置不当,有可能导致目录跨越。

很多管理员都知道设置open_basedir,但在配置不当的时候可能发生目录跨越的问题。

错误的配置:/tmp:/home/www,正确的配置:/tmp/:/home/www/

 代码如下 复制代码

……
/* Resolve open_basedir to resolved_basedir */
if (expand_filepath(local_open_basedir, resolved_basedir TSRMLS_CC) != NULL) {
/* Handler for basedirs that end with a / */
resolved_basedir_len = strlen(resolved_basedir);
if (basedir[strlen(basedir) - 1] == PHP_DIR_SEPARATOR) {
if (resolved_basedir[resolved_basedir_len - 1] != PHP_DIR_SEPARATOR) {
resolved_basedir[resolved_basedir_len] = PHP_DIR_SEPARATOR;
resolved_basedir[++resolved_basedir_len] = '/0';
}
} else {
resolved_basedir[resolved_basedir_len++] = PHP_DIR_SEPARATOR;
resolved_basedir[resolved_basedir_len] = '/0';
}
……

php考虑了以/结束的路径,但是如果没有/,就直接带入下文比较了。

于是,当新建一个网站为 /home/wwwoldjun/(均已经分别设置open_basedir),如果配置错误,则可以从/home/www/目录跳转到/home/wwwoldjun/目录。

举个渗透实例,某idc商在租用虚拟主机的时候如此分配空间/home/wwwroot/userxxx/、/home/wwwroot/useryyy/...,而open_basedir是这样错误配置的:/tmp:/home/wwwroot/userxxx、/tmp:/home/wwwroot/useryyy。如果我们想通过配置的错误轻易渗透下userxxx站点,我们该怎么做?


特殊值 . 指明脚本的工作目录将被作为基准目录。但这有些危险,因为脚本的工作目录可以轻易被 chdir() 而改变。

在 httpd.conf 文件中中,open_basedir 可以像其它任何配置选项一样用“php_admin_value open_basedir none”的方法关闭(例如某些虚拟主机中)。

在 Windows 中,用分号分隔目录。在任何其它系统中用冒号分隔目录。作为 Apache 模块时,父目录中的 open_basedir 路径自动被继承。

用 open_basedir 指定的限制实际上是前缀,不是目录名。也就是说“open_basedir = /dir/incl”也会允许访问“/dir/include”和“/dir/incls”,如果它们存在的话。如果要将访问限制在仅为指定的目录,用斜线结束路径名。例如:“open_basedir = /dir/incl/”。

在php中如果我们要使用PHP Mcrypt加密扩展库就必须先安装好这个加密扩展库,然后再可以使用,因为它与gd库一样默认是未安装的哦。

mcrypt简单介绍

PHP程序员们在编写代码程序时,除了要保证代码的高性能之外,还有一点是非常重要的,那就是程序的安全性保障。PHP除了自带的几种加密函数外,还有功能更全面的PHP加密扩展库Mcrypt和Mhash。
其中,Mcrypt扩展库可以实现加密解密功能,就是既能将明文加密,也可以密文还原。
mcrypt 是 php 里面重要的加密支持扩展库,linux环境下:该库在默认情况下不开启。window环境下:PHP>=5.3,默认开启mcrypt扩展。

1、Mcrypt()库的安装

mcypt是一个功能十分强大的加密算法扩展库。在标准的PHP安装过程中并没有把Mcrypt安装上,但PHP的主目录下包含了libmcrypt.dll文件,所以我们只用将PHP配置文件中的这行:extension=php_mcrypt.dll前面的分号去掉,然后重启服务器就可以使用这个扩展库了。

支持的算法和加密模式

Mcrypt库支持20多种加密算法和8种加密模式,具体可以通过函数mcrypt_list_algorithms()和mcrypt_list_modes()来显示[1]加密算法
Mcrypt支持的算法有:
cast-128
gost
rijndael-128
twofish
arcfour
cast-256
loki97
rijndael-192
saferplus
wake
blowfish-compat
des
rijndael-256
serpent
xtea
blowfish
enigma
rc2
tripledes
加密模式
Mcrypt支持的加密模式有:
cbc
cfb
ctr
ecb
ncfb
nofb
ofb
stream
这些算法和模式在应用中要以常量来表示,写的时候加上前缀MCRYPT_和MCRYPT_来表示,如下面Mcrypt应用的


例子


DES算法表示为MCRYPT_DES;
ECB模式表示为MCRYPT_MODE_ECB;

 代码如下 复制代码

<?php
$str = "我的名字是?一般人我不告诉他!"; //加密内容
$key = "key:111"; //密钥
$cipher = MCRYPT_DES; //密码类型
$modes = MCRYPT_MODE_ECB; //密码模式
$iv = mcrypt_create_iv(mcrypt_get_iv_size($cipher,$modes),MCRYPT_RAND);//初始化向量
echo "加密明文:".$str."<p>";
$str_encrypt = mcrypt_encrypt($cipher,$key,$str,$modes,$iv); //加密函数
echo "加密密文:".$str_encrypt." <p>";
$str_decrypt = mcrypt_decrypt($cipher,$key,$str_encrypt,$modes,$iv); //解密函数
echo "还原:".$str_decrypt;
?>

运行结果:

加密明文:我的名字是?一般人我不告诉他!
加密密文: 锍??]??q???L 笑 ??"? ?

还原:我的名字是?一般人我不告诉他!

<1>由例子中可看到,使用PHP加密扩展库Mcrypt对数据加密和解密之前,首先创建了一个初始化向量,简称为iv。由 $iv = mcrypt_create_iv(mcrypt_get_iv_size($cipher,$modes),MCRYPT_RAND);可见创建初始化向 量需要两个参数:size指定了iv的大小;source为iv的源,其中值MCRYPT_RAND为系统随机数。

<2>函数mcrypt_get_iv_size($cipher,$modes)返回初始化向量大小,参数cipher和mode分别指算法和加 密模式。
<3>加密函数$str_encrypt = mcrypt_encrypt($cipher,$key,$str,$modes,$iv); 该函数的5个参数分 别如下:cipher——加密算法、key——密钥、data(str)——需要加密的数据、mode——算法模式、 iv——初始化向量

<4>解密函数 mcrypt_decrypt($cipher,$key,$str_encrypt,$modes,$iv); 该函数和加密函数的参数几乎 一样,唯一不同的是data,也就是说data为需要解密的数据$str_encrypt,而不是原始数据$str。
注:加密和解密函数中的参数cipher、key和mode必须一一对应,否则数据不能被还原


总结

mcrypt库常量
Mcrypt库支持20多种加密算法和8种加密模式。可以通过函数mcrypt_list_algorithms()和mcrypt_list_modes()来查看。

这里小编来给大家分享一些站长总结出来的防止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 www.12345.com 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用户的和组具有写的权限。

str_replace()函数的使用就是用来替换指定字符了,那么我们正好可以利用它这一点来过滤敏感字符以太到防注入的效果,下面我来给大家总结了一些方法,给大家分享一下。


PHP各种过滤字符函数

 

 代码如下 复制代码

   <?php
    /**
    * 安全过滤函数
    *
    * @param $string
    * @return string
    */
    function safe_replace($string) {
    $string = str_replace('%20','',$string);
    $string = str_replace('%27','',$string);
    $string = str_replace('%2527','',$string);
    $string = str_replace('*','',$string);
    $string = str_replace('"','&quot;',$string);
    $string = str_replace("'",'',$string);
    $string = str_replace('"','',$string);
    $string = str_replace(';','',$string);
    $string = str_replace('<','&lt;',$string);
    $string = str_replace('>','&gt;',$string);
    $string = str_replace("{",'',$string);
    $string = str_replace('}','',$string);
    $string = str_replace('','',$string);
    return $string;
    }
    ?>


    <?php
    /**
    * 返回经addslashes处理过的字符串或数组
    * @param $string 需要处理的字符串或数组
    * @return mixed
    */
    function new_addslashes($string) {
    if(!is_array($string)) return addslashes($string);
    foreach($string as $key => $val) $string[$key] = new_addslashes($val);
    return $string;
    }
    ?>


    <?php
    //对请求的字符串进行安全处理
    /*
    $safestep
    0 为不处理,
    1 为禁止不安全HTML内容(javascript等),
    2 完全禁止HTML内容,并替换部份不安全字符串(如:eval(、union、CONCAT(、--、等)
    */
    function StringSafe($str, $safestep=-1){
    $safestep = ($safestep > -1) ? $safestep : 1;
    if($safestep == 1){
    $str = preg_replace("#script:#i", "script:", $str);
    $str = preg_replace("#<[/]{0,1}(link|meta|ifr|fra|scr)[^>]*>#isU", '', $str);
    $str = preg_replace("#[ ]{1,}#", ' ', $str);
    return $str;
    }else if($safestep == 2){
    $str = addslashes(htmlspecialchars(stripslashes($str)));
    $str = preg_replace("#eval#i", 'eval', $str);
    $str = preg_replace("#union#i", 'union', $str);
    $str = preg_replace("#concat#i", 'concat', $str);
    $str = preg_replace("#--#", '--', $str);
    $str = preg_replace("#[ ]{1,}#", ' ', $str);
    return $str;
    }else{
    return $str;
    }
    }
    ?>


    <?php
       /**
        +----------------------------------------------------------
        * 输出安全的html,用于过滤危险代码
        +----------------------------------------------------------
        * @access public
        +----------------------------------------------------------
        * @param string $text 要处理的字符串
        * @param mixed $tags 允许的标签列表,如 table|td|th|td
        +----------------------------------------------------------
        * @return string
        +----------------------------------------------------------
        */
       static public function safeHtml($text, $tags = null)
       {
           $text =  trim($text);
           //完全过滤注释
           $text = preg_replace('/<!--?.*-->/','',$text);
           //完全过滤动态代码
           $text =  preg_replace('/<?|?'.'>/','',$text);
           //完全过滤js
           $text = preg_replace('/<script?.*/script>/','',$text);
           $text =  str_replace('[','&#091;',$text);
           $text = str_replace(']','&#093;',$text);
           $text =  str_replace('|','&#124;',$text);
           //过滤换行符
           $text = preg_replace('/ ? /','',$text);
           //br
           $text =  preg_replace('/<br(s/)?'.'>/i','[br]',$text);
           $text = preg_replace('/([br]s*){10,}/i','[br]',$text);
           //过滤危险的属性,如:过滤on事件lang js
           while(preg_match('/(<[^><]+)(lang|on|action|background|codebase|dynsrc|lowsrc)[^><]+/i',$text,$mat)){
               $text=str_replace($mat[0],$mat[1],$text);
           }
           while(preg_match('/(<[^><]+)(window.|javascript:|js:|about:|file:|document.|vbs:|cookie)([^><]*)/i',$text,$mat)){
               $text=str_replace($mat[0],$mat[1].$mat[3],$text);
           }
           if( empty($allowTags) ) { $allowTags = self::$htmlTags['allow']; }
           //允许的HTML标签
           $text =  preg_replace('/<('.$allowTags.')( [^><[]]*)>/i','[12]',$text);
           //过滤多余html
           if ( empty($banTag) ) { $banTag = self::$htmlTags['ban']; }
           $text =  preg_replace('/</?('.$banTag.')[^><]*>/i','',$text);
           //过滤合法的html标签
           while(preg_match('/<([a-z]+)[^><[]]*>[^><]*</1>/i',$text,$mat)){
               $text=str_replace($mat[0],str_replace('>',']',str_replace('<','[',$mat[0])),$text);
           }
           //转换引号
           while(preg_match('/([[^[]]*=s*)("|')([^2=[]]+)2([^[]]*])/i',$text,$mat)){
               $text=str_replace($mat[0],$mat[1].'|'.$mat[3].'|'.$mat[4],$text);
           }
           //空属性转换
           $text =  str_replace('''','||',$text);
           $text = str_replace('""','||',$text);
           //过滤错误的单个引号
           while(preg_match('/[[^[]]*("|')[^[]]*]/i',$text,$mat)){
               $text=str_replace($mat[0],str_replace($mat[1],'',$mat[0]),$text);
           }
           //转换其它所有不合法的 < >
           $text =  str_replace('<','&lt;',$text);
           $text = str_replace('>','&gt;',$text);
           $text = str_replace('"','&quot;',$text);
           //反转换
           $text =  str_replace('[','<',$text);
           $text =  str_replace(']','>',$text);
           $text =  str_replace('|','"',$text);
           //过滤多余空格
           $text =  str_replace('  ',' ',$text);
           return $text;
       }
    ?>


    <?php
    function RemoveXSS($val) {
       // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
       // this prevents some character re-spacing such as <javascript>
       // note that you have to handle splits with , , and later since they *are* allowed in some          // inputs
       $val = preg_replace('/([x00-x08,x0b-x0c,x0e-x19])/', '', $val);
       // straight replacements, the user should never need these since they're normal characters
       // this prevents like <IMG SRC=@avascript:alert('XSS')>
       $search = 'abcdefghijklmnopqrstuvwxyz';
       $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
       $search .= '1234567890!@#$%^&*()';
       $search .= '~`";:?+/={}[]-_|'';
       for ($i = 0; $i < strlen($search); $i++) {
           // ;? matches the ;, which is optional
           // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars
           // @ @ search for the hex values
           $val = preg_replace('/(&#[xX]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val);//with a ;
           // @ @ 0{0,7} matches '0' zero to seven times
           $val = preg_replace('/(&#0{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
       }
       // now the only remaining whitespace attacks are , , and 
       $ra1 = Array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
       $ra2 = Array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
       $ra = array_merge($ra1, $ra2);
       $found = true; // keep replacing as long as the previous round replaced something
       while ($found == true) {
           $val_before = $val;
           for ($i = 0; $i < sizeof($ra); $i++) {
               $pattern = '/';
               for ($j = 0; $j < strlen($ra[$i]); $j++) {
                   if ($j > 0) {
                       $pattern .= '(';
                       $pattern .= '(&#[xX]0{0,8}([9ab]);)';
                       $pattern .= '|';
                       $pattern .= '|(&#0{0,8}([9|10|13]);)';
                       $pattern .= ')*';
                   }
                   $pattern .= $ra[$i][$j];
               }
               $pattern .= '/i';
               $replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2); // add in <> to nerf the tag
               $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
               if ($val_before == $val) {
                   // no replacements were made, so exit the loop
                   $found = false;
               }
           }
       }
       return $val;
    }
    ?>

[!--infotagslink--]

相关文章

  • php 中file_get_contents超时问题的解决方法

    file_get_contents超时我知道最多的原因就是你机器访问远程机器过慢,导致php脚本超时了,但也有其它很多原因,下面我来总结file_get_contents超时问题的解决方法总结。...2016-11-25
  • HTTP 408错误是什么 HTTP 408错误解决方法

    相信很多站长都遇到过这样一个问题,访问页面时出现408错误,下面一聚教程网将为大家介绍408错误出现的原因以及408错误的解决办法。 HTTP 408错误出现原因: HTT...2017-01-22
  • Android子控件超出父控件的范围显示出来方法

    下面我们来看一篇关于Android子控件超出父控件的范围显示出来方法,希望这篇文章能够帮助到各位朋友,有碰到此问题的朋友可以进来看看哦。 <RelativeLayout xmlns:an...2016-10-02
  • ps把文字背景变透明的操作方法

    ps软件是现在非常受大家喜欢的一款软件,有着非常不错的使用功能。这次文章就给大家介绍下ps把文字背景变透明的操作方法,喜欢的一起来看看。 1、使用Photoshop软件...2017-07-06
  • php抓取网站图片并保存的实现方法

    php如何实现抓取网页图片,相较于手动的粘贴复制,使用小程序要方便快捷多了,喜欢编程的人总会喜欢制作一些简单有用的小软件,最近就参考了网上一个php抓取图片代码,封装了一个php远程抓取图片的类,测试了一下,效果还不错分享...2015-10-30
  • intellij idea快速查看当前类中的所有方法(推荐)

    这篇文章主要介绍了intellij idea快速查看当前类中的所有方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-09-02
  • Mysql select语句设置默认值的方法

    1.在没有设置默认值的情况下: 复制代码 代码如下:SELECT userinfo.id, user_name, role, adm_regionid, region_name , create_timeFROM userinfoLEFT JOIN region ON userinfo.adm_regionid = region.id 结果:...2014-05-31
  • js导出table数据到excel即导出为EXCEL文档的方法

    复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta ht...2013-10-13
  • js基础知识(公有方法、私有方法、特权方法)

    本文涉及的主题虽然很基础,在许多人看来属于小伎俩,但在JavaScript基础知识中属于一个综合性的话题。这里会涉及到对象属性的封装、原型、构造函数、闭包以及立即执行表达式等知识。公有方法 公有方法就是能被外部访问...2015-11-08
  • mysql 批量更新与批量更新多条记录的不同值实现方法

    批量更新mysql更新语句很简单,更新一条数据的某个字段,一般这样写:复制代码 代码如下:UPDATE mytable SET myfield = 'value' WHERE other_field = 'other_value';如果更新同一字段为同一个值,mysql也很简单,修改下where即...2013-10-04
  • c#中分割字符串的几种方法

    单个字符分割 string s="abcdeabcdeabcde"; string[] sArray=s.Split('c'); foreach(string i in sArray) Console.WriteLine(i.ToString()); 输出下面的结果: ab de...2020-06-25
  • PHP 验证码不显示只有一个小红叉的解决方法

    最近想自学PHP ,做了个验证码,但不知道怎么搞的,总出现一个如下图的小红叉,但验证码就是显示不出来,原因如下 未修改之前,出现如下错误; (1)修改步骤如下,原因如下,原因是apache权限没开, (2)点击打开php.int., 搜索extension=ph...2013-10-04
  • 安卓手机wifi打不开修复教程,安卓手机wifi打不开解决方法

    手机wifi打不开?让小编来告诉你如何解决。还不知道的朋友快来看看。 手机wifi是现在生活中最常用的手机功能,但是遇到手机wifi打不开的情况该怎么办呢?如果手机wifi...2016-12-21
  • ps怎么制作倒影 ps设计倒影的方法

    ps软件是一款非常不错的图片处理软件,有着非常不错的使用效果。这次文章要给大家介绍的是ps怎么制作倒影,一起来看看设计倒影的方法。 用ps怎么做倒影最终效果&#819...2017-07-06
  • 连接MySql速度慢的解决方法(skip-name-resolve)

    最近在Linux服务器上安装MySql5后,本地使用客户端连MySql速度超慢,本地程序连接也超慢。 解决方法:在配置文件my.cnf的[mysqld]下加入skip-name-resolve。原因是默认安装的MySql开启了DNS的反向解析。如果禁用的话就不能...2015-10-21
  • js控制页面控件隐藏显示的两种方法介绍

    javascript控制页面控件隐藏显示的两种方法,方法的不同之处在于控件隐藏后是否还在页面上占位 方法一: 复制代码 代码如下: document.all["panelsms"].style.visibility="hidden"; document.all["panelsms"].style.visi...2013-10-13
  • C#方法的总结详解

    本篇文章是对C#方法进行了详细的总结与介绍,需要的朋友参考下...2020-06-25
  • Zend studio文件注释模板设置方法

    步骤:Window -> PHP -> Editor -> Templates,这里可以设置(增、删、改、导入等)管理你的模板。新建文件注释、函数注释、代码块等模板的实例新建模板,分别输入Name、Description、Patterna)文件注释Name: 3cfileDescriptio...2013-10-04
  • EXCEL数据上传到SQL SERVER中的简单实现方法

    EXCEL数据上传到SQL SERVER中的方法需要注意到三点!注意点一:要把EXCEL数据上传到SQL SERVER中必须提前把EXCEL传到服务器上.做法: 在ASP.NET环境中,添加一个FileUpload上传控件后台代码的E.X: 复制代码 代码如下: if...2013-09-23
  • JS实现随机生成验证码

    这篇文章主要为大家详细介绍了JS实现随机生成验证码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-06