如何利用php过滤sql注入函数函数php过滤sql注入函数

jQuery整理笔记三----jQuery过滤函数
在前面介绍了许多功能实用的选择器,jQuery在此基础上还拓展了许多功能函数,这些函数作为jQuery对象的方法直接实用,这样就能够在选择器的基础上更加精确地控制对象。请注意:筛选函数与选择器在用法上是不同的。例如,在下面这个列表结构中。
&li&1&/li&
&li&2&/li&
&li&3&/li&
如果要设置第二个列表项的字体颜色为红色,可以用选择器进行选择
$("li:eq(1)").css("color","red");
而如果使用过滤函数,则可以使用如下方法来实现
$("li").eq(1).css("color","red");
选择器是构建jQuery对象的基础,而过滤函数则是jQuery对象的成员,用法截然不同,jQuery定义的过滤函数如下表所示:
表2-7 jQuery过滤函数
jQuery过滤函数
获得指定索引值位置上的元素,索引值从0开始计数
hasClass(class)
检查当前元素是否含有某个特定的类,如果有则返回true
filter(expr)
筛选出与指定表达式匹配的元素集合,这个方法用于缩小匹配的范围,用逗号分隔多个表达式
filter(fn)
筛选出与指定函数返回值匹配的元素集合
用一个表达式来检查当前选择的元素集合,如果其中至少有一个元素符合这个给定的表达式就返回true
map(callback)
将一组元素转换成其他数组(不论是否是元素数组)
删除与指定表达式匹配的元素
slice(start,[end])
选取一个匹配的子集,与原来的slice方法类似
把与表达式匹配的元素添加到jQuery对象中。这个函数可以用于连接分别与两个表达式匹配的元素结果集
children([expr])
取得一个包含匹配的元素集合中每一个元素的所有子元素的元素集合
contents()
查找匹配元素内部所有的子节点(包括文本节点)。如果元素是一个ifame,则查找文本内容
find (expr)
搜索所有与指定表达式匹配的元素。这个元素是找出正在处理的元素的后代元素
next([expr])
取得一个包含匹配的元素集合中每一个元素紧邻的后面同辈元素的元素集合
nextAll([expr])
查找当前元素之后的所有元素
parent([expr])
取得一个包含着所有匹配元素的唯一父元素的元素集合
parents([expr])
取得一个包含着所有匹配元素的祖先元素的元素集合(不包含根元素)
prev([expr])
取得一个包含匹配的元素集合中每一个元素紧邻的前一个同辈元素的元素集合
prevAll([expr])
查找当前元素之前所有的同辈元素,可以用表达式过滤
siblings([expr])
取得一个包含匹配的元素集合中每一个元素的所有唯一同辈元素的元素集合。可以用可选的表达式进行筛选
加入先前所选的当前元素中,对于筛选或查找后的元素,加入先前所选元素的将会很有用
回到最近的一个‘破坏性’操作之前,即将匹配的元素列表变为前一次的状态
1、find() 和 filter()两者的区别
简单的说就是find()是在jQuery对象集合的所有的子元素中查找,而filter()是在jQuery对象集合中查找。
还有就是两者参数的区别,find()需要的参数是且只是jQuery选择器的表达式,而filter()的参数可以是jQuery选择器的表达式,也可以是多个jQuery选择器的表达式并列,中间用逗号隔开(逻辑或的关系),filter()参数也可以是一个函数,调用函数时自动传入index参数(jQuery对象集合的长度),函数需返回true或者false来选中或者排除元素。看个例子就明白两者的用法了:
&!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"&
&meta http-equiv="Content-Type" content="text/ charset=gb2312"&
&title&Document&/title&
src="jquery-2.1.0.min.js" type="text/javascript"&&/script&
$(function(){
$('#btn1').click(function(){
alert('这样的jQuery对象有'+$('div').find('.test').length+'个')
$('#btn2').click(function(){
alert('这样的jQuery对象有'+$('div').filter('.test').length+'个');
$('#btn3').click(function(){
alert('这样的jQuery对象有'+$('div').filter('.last').length+'个');
$('#btn4').click(function(){
alert('这样的jQuery对象有'+$('div').filter('.test,.last').length+'个');
$('#btn5').click(function(){
alert('这样的jQuery对象有'+$('div').filter(function(index){
return $(this).hasClass("haha");//检查当前元素是否含有haha类
}).length+'个')
&input type="button" value="test-find" id="btn1" /&
&input type="button" value="test-filter" id="btn2" /&
&input type="button" value="test-filter" id="btn3" /&
&input type="button" value="test-filter" id="btn4" /&
&input type="button" value="test-filter" id="btn5" /&
&div class="first"&
first content
&span class="test"&
test content
&span class="test"&
test1 content
&div class="last"&
&span class="test"&
last test content
&div class="last"&
last no test content
&div class="haha"&
2、map和each的区别
$.map(array,fn(value))的作用是将一个数组转换成另一个数组,循环传递数组内的每个元素(value)进行处理,将所有的返回值组成一个新的数组。
特别需要注意的是.$map()不能处理json格式的数组。
$.each(array,fn(value))的作用是循环处理数组中的各个元素,也就是相当于java中的for循环,它没有返回值。它可以处理json格式的数组。
分别看一下例子就了解这两个函数的区别了
实例3-2 $.map()例子:
&!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&
&title&$.map()函数&/title&
src="jquery-2.1.0.min.js" type="text/javascript"&&/script&
&script language="javascript"&
$(function(){
var aArr = ["a", "b", "c", "d", "e"];
$("p:eq(0)").text(aArr.join());
aArr = $.map(aArr,function(value,index){
//将数组转化为大写并添加序号
return (value.toUpperCase() + index);
$("p:eq(1)").text(aArr.join());
aArr = $.map(aArr,function(value){
//将数组元素的值双份处理
return value +
$("p:eq(2)").text(aArr.join());
&p&&/p&&p&&/p&&p&&/p&
&/html&执行结果如图:
实例3-3 $,each例子:
var arr = { "tom": "汤姆", "jerry": "杰瑞", "lily": "莉莉" };//json格式的对象(dict)
$.each(arr, function(key, value) { alert(key+"="+value); });3、not()用法
需要参数为jQuery选择器的表达式
例如,要从jQuery对象集合中删除id为seleced的
$("p").not("#selected")
4、slice(start,[end])
根据下标选取匹配的子集
&!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&
src="jquery-2.1.0.min.js" type="text/javascript"&&/script&
&script type="text/javascript"&
$(function(){
$("body").html($("p").slice(0, 1))
&p&Hello&/p&&p&cruel&/p&&p&World&/p&
执行结果:Hello
没整理完,以后再补充。。
没有更多推荐了,
不良信息举报
举报内容:
jQuery整理笔记三----jQuery过滤函数
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!tp3.1.3的I函数如何过滤空格 - ThinkPHP框架
如题,如何配置或者书写让I函数过滤接收内容两端和中间的空格?
liangkaihua
积分:2739
ThinkPHP 是一个免费开源的,快速、简单的面向对象的 轻量级PHP开发框架 ,创立于2006年初,遵循Apache2开源协议发布,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。ThinkPHP从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,也注重易用性。并且拥有众多的原创功能和特性,在社区团队的积极参与下,在易用性、扩展性和性能方面不断优化和改进,已经成长为国内最领先和最具影响力的WEB应用开发框架,众多的典型案例确保可以稳定用于商业以及门户级的开发。如何用Excel筛选数据,这7个操作方法你要牢记!
筛选是我们在使用Excel时的基本功能之一,但有关于筛选的操作,你真的都知道吗?
你的答案如果不确定,那下面就和小编一起来盘点一下那些常用的筛选操作。
1、单一精确条件或多条件筛选
这是筛选最基础的操作技能,我们可以对表格数据进行进行单一的精确条件筛选,也可以同时选择多个条件进行数据的筛选。如下动图:
2、使用搜索框进行模糊条件筛选
通过各个条件选项的勾选,我们可以做出精确的筛选,同时也可以使用搜索框,进行模糊条件的筛选,还可以涉及到通配符【*】、占位符【?】的使用。如下动图:
3、按颜色进行筛选
如果我们在数据整理过程中针对部分特定数据进行了颜色区分,这时也可以按照颜色进行筛选。如下动图:
4、按数值范围或文本进行筛选
对表格数据的筛选,还可以按照一定的数值范围、高于或者低于平均值或者指定的文本进行。如下动图:
5、按所选单元格的值进行筛选
如果要筛选出同样值,还可以根据所选中的单元格指定值进行快速筛选。如下动图:
6、高级筛选实现Vlookup函数效果
对于查询函数Vlookup,大家应该都很熟悉。在这里,我们可以利用高级筛选,实现和Vlookup函数一样的查询效果。如下动图:
7、高级筛选去掉重复值
去掉重复值,之前在《提取不重复值,老司机来带路!》这篇文章里有提到过。这里我们再演示一下:
以上这7个关于表格数据筛选的操作如果你不会,还敢说你会筛选么?!赶紧动手操作检验一下吧~
来源:网络,作者不详,如有侵权,请联系我们删除
责任编辑:
声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。
今日搜狐热点巧用函数让excel表格的序号在筛选、插入、删除、隐藏内容时始终连续巧用函数让excel表格的序号在筛选、插入、删除、隐藏内容时始终连续六分智商百家号使用excel表格时我们常常遇到这样的问题,就是在excel表格中进行筛选、插入、删除、隐藏操作之后,设置的序号那一列中的序号就不连续了。往往在插入数据、删除数据之后需要重新输入序号,在筛选、隐藏数据之后呢,由于序号不连续,查看数据的时候感觉很不方便。那么有没有办法来解决呢?当然有!下面我们就打开2016年中国各省GDP排名表来看一看:1、我们来通过筛选看一看华北地区省份的排名,结果看起来很不舒服。如果数据较大的时候就很难一眼看出某一个省份在该地区中的排名了。2、我们再插入一行数据。3、我们来删除一行数据看看怎么样呢?4、隐藏一部分数据之后呢下面我们就来看看巧用SUBTOTAL函数是怎么产生神奇的效果的呢?在A2单元格中输入=SUBTOTAL(103,B$2:B2)*1,然后在单元格右下角双击对所有行进行填充,我们的效果就出现啦!我们再来筛选看一看非常好,筛选之后序号竟然连续起来啦,插入、删除、隐藏操作就不多做演示啦。还不会的小伙伴们,赶快打开EXCEL试一试吧!觉得有用呢,就请关注我,点赞哦!本文仅代表作者观点,不代表百度立场。系作者授权百家号发表,未经许可不得转载。六分智商百家号最近更新:简介:在学习和分享的快乐中提升自我!作者最新文章相关文章php 安全过滤函数代码 - lbsf - 博客园
php 安全过滤函数代码,防止用户恶意输入内容。
//安全过滤输入[jb] function check_str($string, $isurl = false) { $string = preg_replace('/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/','',$string); $string = str_replace(array("\0","%00","\r"),'',$string); empty($isurl) && $string = preg_replace("/&(?!(#[0-9]+|[a-z]+);)/si",'&',$string); $string = str_replace(array("%3C",'&'),'&',$string); $string = str_replace(array("%3E",'&'),'&',$string); $string = str_replace(array('"',"'","\t",' '),array('&','&',' ',' '),$string); return trim($string); }
* 安全过滤类-过滤javascript,css,iframes,object等不安全参数 过滤级别高
Controller中使用方法:$this-&controller-&fliter_script($value)
string $value 需要过滤的值
* @return string
function fliter_script($value) {
$value = preg_replace("/(javascript:)?on(click|load|key|mouse|error|abort|move|unload|change|dblclick|move|reset|resize|submit)/i","&111n\\2",$value);
$value = preg_replace("/(.*?)&\/script&/si","",$value);
$value = preg_replace("/(.*?)&\/iframe&/si","",$value);
$value = preg_replace ("//iesU", '', $value);
* 安全过滤类-过滤HTML标签
Controller中使用方法:$this-&controller-&fliter_html($value)
string $value 需要过滤的值
* @return string
function fliter_html($value) {
if (function_exists('htmlspecialchars')) return htmlspecialchars($value);
return str_replace(array("&", '"', "'", "&", "&"), array("&", "\"", "'", "&", "&"), $value);
* 安全过滤类-对进入的数据加下划线 防止SQL注入
Controller中使用方法:$this-&controller-&fliter_sql($value)
string $value 需要过滤的值
* @return string
function fliter_sql($value) {
$sql = array("select", 'insert', "update", "delete", "\'", "\/\*",
"\.\.\/", "\.\/", "union", "into", "load_file", "outfile");
$sql_re = array("","","","","","","","","","","","");
return str_replace($sql, $sql_re, $value);
* 安全过滤类-通用数据过滤
Controller中使用方法:$this-&controller-&fliter_escape($value)
* @param string $value 需要过滤的变量
* @return string|array
function fliter_escape($value) {
if (is_array($value)) {
foreach ($value as $k =& $v) {
$value[$k] = self::fliter_str($v);
$value = self::fliter_str($value);
* 安全过滤类-字符串过滤 过滤特殊有危害字符
Controller中使用方法:$this-&controller-&fliter_str($value)
string $value 需要过滤的值
* @return string
function fliter_str($value) {
$badstr = array("\0", "%00", "\r", '&', ' ', '"', "'", "&", "&", "
", "%3C", "%3E");
$newstr = array('', '', '', '&', ' ', '"', ''', "&", "&", "
", "&", "&");
= str_replace($badstr, $newstr, $value);
= preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1', $value);
* 私有路劲安全转化
Controller中使用方法:$this-&controller-&filter_dir($fileName)
* @param string $fileName
* @return string
function filter_dir($fileName) {
$tmpname = strtolower($fileName);
$temp = array(':/',"\0", "..");
if (str_replace($temp, '', $tmpname) !== $tmpname) {
return $fileN
* 过滤目录
Controller中使用方法:$this-&controller-&filter_path($path)
* @param string $path
* @return array
public function filter_path($path) {
$path = str_replace(array("'",'#','=','`','$','%','&',';'), '', $path);
return rtrim(preg_replace('/(\/){2,}|(\\\){1,}/', '/', $path), '/');
* 过滤PHP标签
Controller中使用方法:$this-&controller-&filter_phptag($string)
* @param string $string
* @return string
public function filter_phptag($string) {
return str_replace(array(''), array('&?', '?&'), $string);
* 安全过滤类-返回函数
Controller中使用方法:$this-&controller-&str_out($value)
string $value 需要过滤的值
* @return string
public function str_out($value) {
$badstr = array("&", "&", "%3C", "%3E");
$newstr = array("&", "&", "&", "&");
= str_replace($newstr, $badstr, $value);
return stripslashes($value); //下划线
php使用正则过滤js脚本代码实例
header("Content-type:text/charset=utf-8");
$str = '&script type="text/javascript" src="dd.js"&&/script&
测试php正则匹配掉js代码测试php正则匹配掉js代码测试php正则匹配掉js代码测试php正则匹配掉js代码测试php正则匹配掉js代码测试php正则匹配掉js代码
&script type="text/javascript" src="123.js"&&/script&
&script type="text/javascript"&
var aa = "sdsds";
alert(aa);
测试php正则匹配掉js代码';
$preg = "/&script[\s\S]*?&\/script&/i";
$newstr = preg_replace($preg,"",$str,3);
//第四个参数中的3表示替换3次,默认是-1,替换全部
一个完整成熟的站点,内容过滤,防注入,加密存储和传输,敏感词屏蔽都是必不可少功能,关于加密传输有cookie加密存储和解密,客户端js加密到php解密和php文件之间的加密传输,涉及的内容较多,如有可能将另开一贴,本贴主要分享一下内容过滤和敏感词屏蔽的经验
一,内容过滤
说起过滤,大概马上会想到addslashes函数,这个常用于防止sql注入,但其实光这些还远远不够,我们要做的常常是将所有不相关的sql关键词全部替换掉,保证发上来的东西放进sql语句里是无法改变sql行为的,所以一般来说,安全起见这两点要求都需要达到
addslashes函数为了不重复转义,一般会需要判断下服务器是否开启了自动转义,然后再进行转义
function add_slashes($string, $force = 0)
&&&&if(!get_magic_quotes_gpc() || $force)
&&&&&&&&if(is_array($string))
&&&&&&&&&&&&foreach($string as $key =& $val)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&$string[$key] = daddslashes($val, $force);
&&&&&&&&&&&&}
&&&&&&&&else
&&&&&&&&&&&&$string = addslashes($string);
&&&&return $string;
 为了让所有的sql关键词都安全存储,我们需要将它们转义,显示的时候再翻译回来
function sql_encode($str)
if(empty($str)) return "";
$str=trim($str);
$str=str_replace("_","\_",$str);
$str=str_replace("%","\%",$str);
$str=str_replace(chr(39),"'",$str);
$str=str_replace("'","''",$str);
$str=str_replace("select","select",$str);
$str=str_replace("join","join",$str);
$str=str_replace("union","union",$str);
$str=str_replace("where","where",$str);
$str=str_replace("insert","insert",$str);
$str=str_replace("delete","delete",$str);
$str=str_replace("update","update",$str);
$str=str_replace("like","like",$str);
$str=str_replace("drop","drop",$str);
$str=str_replace("create","create",$str);
$str=str_replace("modify","modify",$str);
$str=str_replace("rename","rename",$str);
$str=str_replace("alter","alter",$str);
$str=str_replace("cast","cas",$str);
return $str;
function sql_decode($str)
if(empty($str)) return "";
$str=str_replace("'",chr(39),$str);
$str=str_replace("''","'",$str);
$str=str_replace("select","select",$str);
$str=str_replace("join","join",$str);
$str=str_replace("union","union",$str);
$str=str_replace("where","where",$str);
$str=str_replace("insert","insert",$str);
$str=str_replace("delete","delete",$str);
$str=str_replace("update","update",$str);
$str=str_replace("like","like",$str);
$str=str_replace("drop","drop",$str);
$str=str_replace("create","create",$str);
$str=str_replace("modify","modify",$str);
$str=str_replace("rename","rename",$str);
$str=str_replace("alter","alter",$str);
$str=str_replace("cas","cast",$str);
return $str;
有了以上的函数,对于sql语句涉及的内容就可以放心使用了,但这还不够,页面显示内容也需要过滤,页面内容过滤也分很多情况,比如标题是不允许html标签的,用户名是除了限制的数字字母,下划线外,其他都不允许使用的,而内容是可以有限制性的使用一些html标签,这就需要我们针对不同情况做不同的过滤处理
1,标题过滤
function filters_title($text)
$text = trim($text);
$text = str_replace("'","",$text);
$text = strip_tags($text);
$text = stripslashes($text);
return $text;
2,用户名过滤
function filters_username($string)
$length=strlen($string);
if($length&2 || $length&18){return false;}
for($n=0; $n&$ $n++)
$t = ord($string[$n]);
if( (47&$t && $t&58) || (64&$t && $t&91) || (96&$t && $t&123) || $t==45 || $t==95 || $t&126){}
else{return false;}
return true;
3,内容过滤
function filters_outcontent($str)
$str = stripslashes($str);
$str = preg_replace("/&div[^&]*?&/is","",$str);
$str = str_replace("aaaaa","\r\n",$str);
$str = str_replace("bbbbb","\n",$str);
$str = str_replace("ccccc","\r",$str);
$str = str_replace('\"','"',$str);
$str = str_replace(array('&HTML', '&BODY', '&INPUT', '&SCRIPT', '&FORM', '&IFRAME'), array('&html', '&body', '&input', '&script', '&form', '&iframe'), $str);
$str = str_replace(array('&html', '&body', '&input', '&script', '&form', '&iframe', '&textarea','&/textarea&'), array('&html', '&body', '&input', '&script', '&form', '&iframe', '&textarea', '&/textarea&'), $str);
return $str;
可以根据以上思路添加自己的过滤场景,做到符合项目要求
二,敏感词屏蔽
敏感词屏蔽是现在国内站点必须使用的功能之一了,国情如此,辛辛苦苦做的站,因为这个被封,实在很不划算。根据应用场景,敏感词过滤可以分为替换和禁止两种,替换就是不提示,直接替换敏感词为**等,禁止一半而言需要提示用户,有敏感词,需要修改,例如在用户注册时候,替换一般用在文章中。
敏感词需要数据库支持,将敏感词存入数据库时候,可以按照分类,那些是要替换的,那些是要禁止的,按照固定格式存储,例如 abc=**,这是替换。cba={banned},这是禁止,或者在函数中制定第二个参数,replace或者banned来制定函数执行替换或者精致操作都可以,我采用的是第一种,如果有需要,大家可以根据原函数修改为第二种,最核心的其实很简单就是个正则查找的过程
function censor($string) {
global $dblink, $tablepre;
$censoraray = $banned = $banwords = array();
$query = $dblink-&query("SELECT * FROM censor WHERE var='censor' ");
if($value = $dblink-&fetch_array($query)) {
$censorstr = is_array($value)?$value['datavalue']:$value;
$censorstr = '';
if (strlen(trim($censorstr)) & 0) {
//有值就屏蔽
$censorarr = explode("\n", $censorstr);//按输入时候的回车分割为数组
foreach($censorarr as $censor) {
$censor = trim($censor);
if(empty($censor)) continue;
list($find, $replace) = explode('=', $censor);
$findword = $find;
$find = preg_replace("/\\\{(\d+)\\\}/", ".{0,\\1}", preg_quote($find, '/'));//匹配屏蔽语法中的"a{1}s{2}s"
switch($replace) {
case '{BANNED}':
$banwords[] = preg_replace("/\\\{(\d+)\\\}/", "*", preg_quote($findword, '/'));
$banned[] = $find;
$censoraray['filter']['find'][] = '/'.$find.'/i';
$censoraray['filter']['replace'][] = $replace;
if($banned) {
$censoraray['banned'] = '/('.implode('|', $banned).')/i';
$censoraray['banword'] = implode(', ', $banwords);
if($censoraray['banned'] && preg_match($censoraray['banned'], $string)) {
return $censoraray['banned'];//有敏感词汇不予显示
$string = empty($censoraray['filter']) ? $string :
@preg_replace($censoraray['filter']['find'], $censoraray['filter']['replace'], $string);
return $string;
因为我采用了第一种,所以需要将敏感词从数据库中取出后,做替换或者禁止的判断,其实核心代码很少,算是给大家一些思路吧
三,cookie加密
cookie加密存储是站点安全的很重要选择步骤,一些敏感的数据存储在cookie里方便了页面之间的传输,或者用于身份认定,来源判断,这些数据如果不加密,对有经验的人来说,很容易就会分析出一些站点的内部机制,或者将cookie用于跨站攻击。
设置cookie的语法很简单
setcookie(name,value,expire,path,domain,secure)
name &&&&&&&&必需。规定 cookie 的名称。
value &&&&&&&&必需。规定 cookie 的值。
expire &&&&&&&&可选。规定 cookie 的有效期。
path &&&&&&&&可选。规定 cookie 的服务器路径。
domain &&&&&&&&可选。规定 cookie 的域名。
secure &&&&&&&&可选。规定是否通过安全的 HTTPS 连接来传输 cookie。
设置cookie的函数可以这样写
function set_cookie($var, $value, $life = 0, $prefix = 1)
global $cookiepre, $cookiedomain, $cookiepath, $timestamp, $_SERVER;
setcookie(($prefix ? $cookiepre : '').$var, $value, $life ? $timestamp + $life : 0, $cookiepath,$cookiedomain, $_SERVER['SERVER_PORT'] == 443 ? 1 : 0);
1,$prefix = 1 所以当($prefix ? $cookiepre : '').$var时候就会加上前缀,也可以选择不加 2,$lift=0 所以当$life ? $timestamp + $life : 0时候,如果传值了且不是0,就会设置有效期
这里最重要的是加密函数,我这里用的是下面这个
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0)
$ckey_length = 4;
//note 随机密钥长度 取值 0-32;
//note 加入随机密钥,可以令密文无任何规律,即便是原文和密钥完全相同,加密结果也会每次不同,增大破解难度。
//note 取值越大,密文变动规律越大,密文变化 = 16 的 $ckey_length 次方
//note 当此值为 0 时,则不产生随机密钥
$key = md5($key ? $key : UC_KEY);
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey);
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
for($i = 0; $i &= 255; $i++)
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
for($j = $i = 0; $i & 256; $i++)
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
for($a = $j = $i = 0; $i & $string_ $i++)
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
if($operation == 'DECODE')
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() & 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16))
return substr($result, 26);
return '';
return $keyc.str_replace('=', '', base64_encode($result));
第二个参数可设置为加密encode,或者解密decode。
这样一来,加密的设置cookie就可以这样写
set_cookie('compound', authcode("$uid\t$uname\t$pw", 'ENCODE', $key));
读取的时候,将cookie值读入变量,然后&$cookiearray=explode("\t", authcod($cookieval, 'DECODE', $key))就可以读入到数组里了。
部分来源:http://www.cnblogs.com/phpinfo/p/3592873.html
&php过滤所有恶意字符:
//php 批量过滤post,get敏感数据
if (get_magic_quotes_gpc()) {
$_GET = stripslashes_array($_GET);
$_POST = stripslashes_array($_POST);
function stripslashes_array(&$array) {
while(list($key,$var) = each($array)) {
if ($key != 'argc' && $key != 'argv' && (strtoupper($key) != $key || ''.intval($key) == "$key")) {
if (is_string($var)) {
$array[$key] = stripslashes($var);
if (is_array($var)) {
$array[$key] = stripslashes_array($var);
function htmlencode($str){
if(empty($str))
if($str=="") return $
$str=trim($str);
$str=str_replace("&","&",$str);
$str=str_replace("&","&",$str);
$str=str_replace("&","&",$str);
$str=str_replace(chr(32)," ",$str);
$str=str_replace(chr(9)," ",$str);
$str=str_replace(chr(9)," ",$str);
$str=str_replace(chr(34),"&",$str);
$str=str_replace(chr(39),"'",$str);
$str=str_replace(chr(13),"
$str=str_replace("'","''",$str);
$str=str_replace("select","select",$str);
$str=str_replace("SCRIPT","SCRIPT",$str);
$str=str_replace("script","script",$str);
$str=str_replace("join","join",$str);
$str=str_replace("union","union",$str);
$str=str_replace("where","where",$str);
$str=str_replace("insert","insert",$str);
$str=str_replace("delete","delete",$str);
$str=str_replace("update","update",$str);
$str=str_replace("like","like",$str);
$str=str_replace("drop","drop",$str);
$str=str_replace("create","create",$str);
$str=str_replace("modify","modify",$str);
$str=str_replace("rename","rename",$str);
$str=str_replace("alter","alter",$str);
$str=str_replace("cast","cas",$str);
function htmldecode($str){
if(empty($str))
if($str=="") return $
$str=str_replace("select","select",$str);
$str=str_replace("join","join",$str);
$str=str_replace("union","union",$str);
$str=str_replace("where","where",$str);
$str=str_replace("insert","insert",$str);
$str=str_replace("delete","delete",$str);
$str=str_replace("update","update",$str);
$str=str_replace("like","like",$str);
$str=str_replace("drop","drop",$str);
$str=str_replace("create","create",$str);
$str=str_replace("modify","modify",$str);
$str=str_replace("rename","rename",$str);
$str=str_replace("alter","alter",$str);
$str=str_replace("cas","cast",$str);
$str=str_replace("&","&",$str);
$str=str_replace("&","&",$str);
$str=str_replace("&","&",$str);
$str=str_replace(" ",chr(32),$str);
$str=str_replace(" ",chr(9),$str);
$str=str_replace(" ",chr(9),$str);
$str=str_replace("&",chr(34),$str);
$str=str_replace("'",chr(39),$str);
$str=str_replace("
",chr(13),$str);
$str=str_replace("''","'",$str);
// 函数:string_filter($string, $match_type=1)
// 功能:过滤非法内容
// $string 需要检查的字符串
// $match_type 匹配类型,1为精确匹配, 2为模糊匹配,默认为1
// 返回:有非法内容返回True,无非法内容返回False
// 其他:非法关键字列表保存在txt文件里, 分为普通非法关键字和严重非法关键字两个列表
// 作者:heiyeluren
//======================================================================
function lib_lawless_string_filter($string, $match_type=1)
//字符串空直接返回为非法
$string = trim($string);
if (empty($string))
//获取重要关键字列表和普通关键字列表
$common_file = "common_list.txt"; //通用过滤关键字列表
$signify_file = "signify_list.txt"; //重要过滤关键字列表
//如果任何列表文件不存在直接返回false,否则把两个文件列表读取到两个数组里
if (!file_exists($common_file) || !file_exists($signify_file))
$common_list = file($common_file);
$signify_list = file($signify_file);
//精确匹配
if ($match_type == 1)
$is_lawless = exact_match($string, $common_list);
//模糊匹配
if ($match_type == 2)
$is_lawless = blur_match($string, $common_list, $signify_list);
//判断检索结果数组中是否有数据,如果有,证明是非法的
if (is_array($is_lawless) && !empty($is_lawless))
//---------------------
// 精确匹配,为过滤服务
//---------------------
function exact_match($string, $common_list)
$string = trim($string);
$string = lib_replace_end_tag($string);
//检索普通过滤关键字列表
foreach($common_list as $block)
$block = trim($block);
if (preg_match("/^$string$/i", $block))
$blist[] = $
//判断有没有过滤内容在数组里
if (!empty($blist))
return array_unique($blist);
//----------------------
// 模糊匹配,为过滤服务
//----------------------
function blur_match($string, $common_list, $signify_list)
$string = trim($string);
$s_len = strlen($string);
$string = lib_replace_end_tag($string);
//检索普通过滤关键字列表
foreach($common_list as $block)
$block = trim($block);
if (preg_match("/^$string$/i", $block))
$blist[] = $
//检索严重过滤关键字列表
foreach($signify_list as $block)
$block = trim($block);
if ($s_len&=strlen($block) && preg_match("/$block/i", $string))
$blist[] = $
//判断有没有过滤内容在数组里
if (!empty($blist))
return array_unique($blist);
//--------------------------
// 替换HTML尾标签,为过滤服务
//--------------------------
function lib_replace_end_tag($str)
if (empty($str))
$str = htmlspecialchars($str);
$str = str_replace( '/', "", $str);
$str = str_replace("\\", "", $str);
$str = str_replace("&", "", $str);
$str = str_replace("&", "", $str);
$str = str_replace("", "", $str);
$str = str_replace("", "", $str);
$str=str_replace("select","select",$str);
$str=str_replace("join","join",$str);
$str=str_replace("union","union",$str);
$str=str_replace("where","where",$str);
$str=str_replace("insert","insert",$str);
$str=str_replace("delete","delete",$str);
$str=str_replace("update","update",$str);
$str=str_replace("like","like",$str);
$str=str_replace("drop","drop",$str);
$str=str_replace("create","create",$str);
$str=str_replace("modify","modify",$str);
$str=str_replace("rename","rename",$str);
$str=str_replace("alter","alter",$str);
$str=str_replace("cas","cast",$str);
$str=str_replace("&","&",$str);
$str=str_replace("&","&",$str);
$str=str_replace("&","&",$str);
$str=str_replace(" ",chr(32),$str);
$str=str_replace(" ",chr(9),$str);
$str=str_replace(" ",chr(9),$str);
$str=str_replace("&",chr(34),$str);
$str=str_replace("'",chr(39),$str);
$str=str_replace("
",chr(13),$str);
$str=str_replace("''","'",$str);
$str=str_replace("css","'",$str);
$str=str_replace("CSS","'",$str);
//HTML标签,可以作为扩展过滤
$tags = array("/html", "/head", "/body", "/div", "/span", "/DOCTYPE", "/title", "/link", "/meta", "/style", "/p", "/h1,", "/h2,", "/h3,", "/h4,", "/h5,", "/h6", "/strong", "/em", "/abbr", "/acronym", "/address", "/bdo", "/blockquote", "/cite", "/q", "/code", "/ins", "/del", "/dfn", "/kbd", "/pre", "/samp", "/var", "/br", "/a", "/img", "/area", "/map", "/object", "/param", "/ul", "/ol", "/li", "/dl", "/dt", "/dd", "/table", "/tr", "/td", "/th", "/tbody", "/thead", "/tfoot", "/col", "/colgroup", "/caption", "/form", "/input", "/textarea", "/select", "/option", "/optgroup", "/button", "/label", "/fieldset", "/legend", "/script", "/noscript", "/b", "/i", "/tt", "/sub", "/sup", "/big", "/small", "/hr" );
引用是直接这样:
$xxx = htmlspecialchars($_POST['xxx']);
$xxx = htmlspecialchars($_GET['xxx']);
作为PHP程序员,特别是新手,对于互联网的险恶总是知道的太少,对于外部的入侵有很多时候是素手无策的,他们根本不知道黑客是如何入侵的、提交入侵、上传漏洞、sql 注入、跨脚本攻击等等。&
作为最基本的防范你需要注意你的外部提交,做好第一面安全机制处理防火墙。
规则 1:绝不要信任外部数据或输入 关于Web应用程序安全性,必须认识到的第一件事是不应该信任外部数据。外部数据(outside data)
包括不是由程序员在PHP代码中直接输入的任何数据。在采取措施确保安全之前,来自任何其他来源(比如 GET 变量、表单 POST、数据库、配置文件、会话变量或
cookie)的任何数据都是不可信任的。
例如,下面的数据元素可以被认为是安全的,因为它们是在PHP中设置的。
&代码如下:
$myUsername = 'tmyer'; $arrayUsers = array('tmyer', 'tom', 'tommy');
define(&GREETING&, 'hello
there' . $myUsername);
但是,下面的数据元素都是有瑕疵的。
2. 不安全、有瑕疵的代码
&代码如下:
$myUsername =
$_POST['username']; //tainted!
$arrayUsers = array($myUsername, 'tom',
'tommy'); //tainted!
define(&GREETING&, 'hello there' . $myUsername);
//tainted!
为 什么第一个变量 $myUsername 是有瑕疵的?因为它直接来自表单
POST。用户可以在这个输入域中输入任何字符串,包括用来清除文件或运行以前上传的文件的恶意命令。您可能会问,&难道不能使用只接受字母 A-Z
的客户端(Javascrīpt)表单检验脚本来避免这种危险吗?&是的,这总是一个有好处的步骤,但是正如在后面会看到的,任何人都可以将任何表单下载
到自己的机器上,修改它,然后重新提交他们需要的任何内容。
解决方案很简单:必须对 $_POST['username']
运行清理代码。如果不这么做,那么在使用 $myUsername 的任何其他时候(比如在数组或常量中),就可能污染这些对象。 对用户输入进行清理的一个简单方法是,使用正则表达式来处理它。在这个示例中,只希望接受字母。将字符串限制为特定数量的字符,或者要求所有字母都是小写的,这可能也是个好主意。 清单 3. 使用户输入变得安全
&代码如下:
$myUsername =
cleanInput($_POST['username']); //clean!
$arrayUsers = array($myUsername,
'tom', 'tommy'); //clean!
define(&GREETING&, 'hello there' . $myUsername);
function cleanInput($input){
$clean = strtolower($input); $clean = preg_replace(&/[^a-z]/&, &&, $clean);
substr($clean,0,12);
2:禁用那些使安全性难以实施的 PHP 设置
已经知道了不能信任用户输入,还应该知道不应该信任机器上配置 PHP
的方式。例如,要确保禁用 register_globals。如果启用了 register_globals,就可能做一些粗心的事情,比如使用 $variable
替换同名的 GET 或 POST 字符串。通过禁用这个设置,PHP 强迫您在正确的名称空间中引用正确的变量。要使用来自表单 POST 的变量,应该引用
$_POST['variable']。这样就不会将这个特定变量误会成 cookie、会话或 GET 变量。
3:如果不能理解它,就不能保护它 一些开发人员使用奇怪的语法,或者将语句组织得很紧凑,形成简短但是含义模糊的代码。这种方式可能效率高,但是如果您不理解代码正在做什么,那么就无法决定如何保护它。 例如,您喜欢下面两段代码中的哪一段?
清单 4. 使代码容易得到保护
&代码如下:
//obfuscated code
(isset($_POST['username']) ? $_POST['username']:&);
//unobfuscated code $input = &;
if (isset($_POST['username'])){
$_POST['username'];
$input = &;
在第二个比较清晰的代码段中,很容易看出 $input 是有瑕疵的,需要进行清理,然后才能安全地处理。
4:&纵深防御& 是新的法宝
本教程将用示例来说明如何保护在线表单,同时在处理表单的 PHP 代码中采用必要的措施。同样,即使使用
PHP regex 来确保 GET 变量完全是数字的,仍然可以采取措施确保 SQL 查询使用转义的用户输入。 纵深防御不只是一种好思想,它可以确保您不会陷入严重的麻烦。
既然已经讨论了基本规则,现在就来研究第一种威胁:SQL 注入攻击。
SQL 注入攻击
在 SQL 注入攻击 中,用户通过操纵表单或 GET
查询字符串,将信息添加到数据库查询中。例如,假设有一个简单的登录数据库。这个数据库中的每个记录都有一个用户名字段和一个密码字段。构建一个登录表单,让用户能够登录。 清单 5. 简单的登录表单
&代码如下:
&head& &title&Login&/title&
&body& &form action=&verify.php& method=&post&&
for='user'&Username&/label&
&input type='text' name='user'
id='user'/&
for='pw'&Password&/label&
&input type='password' name='pw'
&p&&input type='submit'
value='login'/&&/p&
&/body& &/html&
这个表单接受用户输入的用户名和密码,并将用户输入提交给名为 verify.php
的文件。在这个文件中,PHP 处理来自登录表单的数据,如下所示:
清单 6. 不安全的 PHP 表单处理代码
&代码如下:
$okay = 0;
$username =
$_POST['user'];
$pw = $_POST['pw'];
$sql = &select count(*) as ctr from
users where username='&.$username.&' and password='&. $pw.&' limit 1&P; $result = mysql_query($sql);
while ($data =
mysql_fetch_object($result)){
if ($data-&ctr == 1){
//they're okay to
enter the application!
$okay = 1;
if ($okay){ $_SESSION['loginokay'] =
header(&index.php&);
}else{ header(&login.php&);
段代码看起来没问题,对吗?世界各地成百(甚至成千)的 PHP/MySQL 站点都在使用这样的代码。它错在哪里?好,记住
&不能信任用户输入&。这里没有对来自用户的任何信息进行转义,因此使应用程序容易受到攻击。具体来说,可能会出现任何类型的 SQL 注入攻击。 例如,如果用户输入 foo 作为用户名,输入 ' or '1&='1 作为密码,那么实际上会将以下字符串传递给 PHP,然后将查询传递给 MySQL:
&代码如下:
$sql = &select count(*) as ctr
from users where username='foo' and password=& or '1&='1& limit 1&P;
这个查询总是返回计数值 1,因此 PHP 会允许进行访问。通过在密码字符串的末尾注入某些恶意 SQL,黑客就能装扮成合法的用户。 解 决这个问题的办法是,将 PHP 的内置 mysql_real_escape_string()
函数用作任何用户输入的包装器。这个函数对字符串中的字符进行转义,使字符串不可能传递撇号等特殊字符并让 MySQL 根据特殊字符进行操作。清单 7
展示了带转义处理的代码。
清单 7. 安全的 PHP 表单处理代码
&代码如下:
$okay = 0;
$username =
$_POST['user'];
$pw = $_POST['pw'];
$sql = &select count(*) as ctr from
users where username='&.mysql_real_escape_string($username).&' and password='&.
mysql_real_escape_string($pw).&' limit 1&P;
$result = mysql_query($sql); while ($data = mysql_fetch_object($result)){
if ($data-&ctr == 1){ //they're okay to enter the application!
$okay = 1;
$_SESSION['loginokay'] =
header(&index.php&);
}else{ header(&login.php&);
mysql_real_escape_string() 作为用户输入的包装器,就可以避免用户输入中的任何恶意 SQL 注入。如果用户尝试通过 SQL
注入传递畸形的密码,那么会将以下查询传递给数据库:
select count(*) as ctr from users where
username='foo' and password='\' or \'1\'=\'1& limit 1&P 数据库中没有任何东西与这样的密码匹配。仅仅采用一个简单的步骤,就堵住了 Web 应用程序中的一个大漏洞。这里得出的经验是,总是应该对 SQL
查询的用户输入进行转义。
但是,还有几个安全漏洞需要堵住。下一项是操纵 GET 变量。
防止用户操纵 GET 变量 在前一节中,防止了用户使用畸形的密码进行登录。如果您很聪明,应该应用您学到的方法,确保对 SQL 语句的所有用户输入进行转义。
是,用户现在已经安全地登录了。用户拥有有效的密码,并不意味着他将按照规则行事 &&
他有很多机会能够造成损害。例如,应用程序可能允许用户查看特殊的内容。所有链接指向 template.php?pid=33 或
template.php?pid=321 这样的位置。URL 中问号后面的部分称为查询字符串。因为查询字符串直接放在 URL 中,所以也称为 GET
查询字符串。
在 PHP 中,如果禁用了 register_globals,那么可以用 $_GET['pid'] 访问这个字符串。在
template.php 页面中,可能会执行与清单 8 相似的操作。
清单 8. 示例 template.php&
&代码如下:
$pid = $_GET['pid'];
create an object of a fictional class Page
$obj = new P
$content =
$obj-&fetchPage($pid);
//and now we have a bunch of PHP that displays the
这 里有什么错吗?首先,这里隐含地相信来自浏览器的 GET 变量 pid
是安全的。这会怎么样呢?大多数用户没那么聪明,无法构造出语义攻击。但是,如果他们注意到浏览器的 URL 位置域中的
pid=33,就可能开始捣乱。如果他们输入另一个数字,那么可能没问题;但是如果输入别的东西,比如输入 SQL 命令或某个文件的名称(比如
/etc/passwd),或者搞别的恶作剧,比如输入长达 3,000 个字符的数值,那么会发生什么呢? 在这种情况下,要记住基本规则,不要信任用户输入。应用程序开发人员知道 template.php 接受的个人标识符(PID)应该是数字,所以可以使用
PHP 的 is_numeric() 函数确保不接受非数字的 PID,如下所示:
清单 9. 使用 is_numeric() 来限制
&代码如下:
$pid = $_GET['pid'];
(is_numeric($pid)){
//we create an object of a fictional class Page
$content = $obj-&fetchPage($pid);
//and now we have a
bunch of PHP that displays the page
//didn't pass the
is_numeric() test, do something else!
这个方法似乎是有效的,但是以下这些输入都能够轻松地通过 is_numeric() 的检查:
100 (有效) 100.1 (不应该有小数位)
+ (科学计数法 && 不好)
0xff33669f (十六进制 && 危险!危险!) 那么,有安全意识的 PHP 开发人员应该怎么做呢?多年的经验表明,最好的做法是使用正则表达式来确保整个 GET 变量由数字组成,如下所示: 清单 10. 使用正则表达式限制 GET 变量
&代码如下:
$pid = $_GET['pid'];
(strlen($pid)){
if (!ereg(&^[0-9]+$&,$pid)){
//do something appropriate,
like maybe logging them out or sending them back to home page
}else{ //empty $pid, so send them back to the home page
//we create an
object of a fictional class Page, which is now
//moderately protected from
evil user input
$obj = new P
$content = $obj-&fetchPage($pid); //and now we have a bunch of PHP that displays the page
需 要做的只是使用 strlen() 检查变量的长度是否非零;如果是,就使用一个全数字正则表达式来确保数据元素是有效的。如果 PID
包含字母、斜线、点号或任何与十六进制相似的内容,那么这个例程捕获它并将页面从用户活动中屏蔽。如果看一下 Page 类幕后的情况,就会看到有安全意识的 PHP
开发人员已经对用户输入 $pid 进行了转义,从而保护了 fetchPage() 方法,如下所示:
清单 11. 对
fetchPage() 方法进行转义
&代码如下:
class Page{
fetchPage($pid){
$sql = &select pid,title,desc,kw,content,status from page
where pid='&.mysql_real_escape_string($pid).&'&;
您可能会问,&既然已经确保 PID 是数字,那么为什么还要进行转义?& 因为不知道在多少不同的上下文和情况中会使用
fetchPage() 方法。必须在调用这个方法的所有地方进行保护,而方法中的转义体现了纵深防御的意义。
如 果用户尝试输入非常长的数值,比如长达
1000 个字符,试图发起缓冲区溢出攻击,那么会发生什么呢?下一节更详细地讨论这个问题,但是目前可以添加另一个检查,确保输入的 PID
具有正确的长度。您知道数据库的 pid 字段的最大长度是 5 位,所以可以添加下面的检查。
清单 12. 使用正则表达式和长度检查来限制
&代码如下:
$pid = $_GET['pid'];
(strlen($pid)){
if (!ereg(&^[0-9]+$&,$pid) && strlen($pid) & 5){ //do something appropriate, like maybe logging them out or sending them back
to home page
//empty $pid, so send them back to the home
//we create an object of a fictional class Page, which is now //even more protected from evil user input
$obj = new P
= $obj-&fetchPage($pid);
//and now we have a bunch of PHP that displays
现在,任何人都无法在数据库应用程序中塞进一个 5,000 位的数值 && 至少在涉及 GET
字符串的地方不会有这种情况。想像一下黑客在试图突破您的应用程序而遭到挫折时咬牙切齿的样子吧!而且因为关闭了错误报告,黑客更难进行侦察。
缓冲区溢出攻击 缓冲区溢出攻击 试图使 PHP 应用程序中(或者更精确地说,在 Apache 或底层操作系统中)的内存分配缓冲区发生溢出。请记住,您可能是使用 PHP
这样的高级语言来编写 Web 应用程序,但是最终还是要调用 C(在 Apache 的情况下)。与大多数低级语言一样,C 对于内存分配有严格的规则。 缓冲区溢出攻击向缓冲区发送大量数据,使部分数据溢出到相邻的内存缓冲区,从而破坏缓冲区或者重写逻辑。这样就能够造成拒绝服务、破坏数据或者在远程服务器上执行恶意代码。 防止缓冲区溢出攻击的惟一方法是检查所有用户输入的长度。例如,如果有一个表单元素要求输入用户的名字,那么在这个域上添加值为 40 的 maxlength
属性,并在后端使用 substr() 进行检查。清单 13 给出表单和 PHP 代码的简短示例。
清单 13. 检查用户输入的长度
&代码如下:
if ($_POST['submit'] == &go&){ $name = substr($_POST['name'],0,40);
action=&&?php echo $_SERVER['PHP_SELF'];?&& method=&post&& &p&&label for=&name&&Name&/label&
type=&text& name=&name& id=&name& size=&20&P maxlength=&40&P/&&/p& &p&&input type=&submit& name=&submit& value=&go&/&&/p& &/form&
为 什么既提供 maxlength 属性,又在后端进行 substr()
检查?因为纵深防御总是好的。浏览器防止用户输入 PHP 或 MySQL 不能安全地处理的超长字符串(想像一下有人试图输入长达 1,000 个字符的名称),而后端
PHP 检查会确保没有人远程地或者在浏览器中操纵表单数据。
正如您看到的,这种方式与前一节中使用 strlen() 检查 GET 变量 pid
的长度相似。在这个示例中,忽略长度超过 5 位的任何输入值,但是也可以很容易地将值截短到适当的长度,如下所示:
清单 14. 改变输入的
GET 变量的长度
&代码如下:
$pid = $_GET['pid'];
(strlen($pid)){
if (!ereg(&^[0-9]+$&,$pid)){
//if non numeric $pid, send
them back to home page
//empty $pid, so send them back to
the home page
//we have a numeric pid, but it may be too long, so
let's check
if (strlen($pid)&5){
$pid = substr($pid,0,5);
} //we create an object of a fictional class Page, which is now
more protected from evil user input
$obj = new P
$content =
$obj-&fetchPage($pid);
//and now we have a bunch of PHP that displays the
注 意,缓冲区溢出攻击并不限于长的数字串或字母串。也可能会看到长的十六进制字符串(往往看起来像
\xA3 或 \xFF)。记住,任何缓冲区溢出攻击的目的都是淹没特定的缓冲区,并将恶意代码或指令放到下一个缓冲区中,从而破坏数据或执行恶意代码。对付十六进制缓
冲区溢出最简单的方法也是不允许输入超过特定的长度。 如果您处理的是允许在数据库中输入较长条目的表单文本区,那么无法在客户端轻松地限制数据的长度。在数据到达 PHP
之后,可以使用正则表达式清除任何像十六进制的字符串。
清单 15. 防止十六进制字符串
&代码如下:
if ($_POST['submit'] == &go&){ $name = substr($_POST['name'],0,40);
//clean out any potential
hexadecimal characters
$name = cleanHex($name);
//continue processing&. }
function cleanHex($input){
preg_replace(&![\][xX]([A-Fa-f0-9]{1,3})!&, &&,$input);
&form action=&&?php echo $_SERVER['PHP_SELF'];?&&
method=&post&&
&p&&label for=&name&&Name&/label& &input type=&text& name=&name& id=&name& size=&20&P
maxlength=&40&P/&&/p&
&p&&input type=&submit& name=&submit&
value=&go&/&&/p&
可能会发现这一系列操作有点儿太严格了。毕竟,十六进制串有合法的用途,比如输出外语中的字符。如何部署十六进制 regex
由您自己决定。比较好的策略是,只有在一行中包含过多十六进制串时,或者字符串的字符超过特定数量(比如 128 或 255)时,才删除十六进制串。 跨站点脚本攻击
在跨站点脚本(XSS)攻击中,往往有一个恶意用户在表单中(或通过其他用户输入方式)输入信息,这些输入将恶
意的客户端标记插入过程或数据库中。例如,假设站点上有一个简单的来客登记簿程序,让访问者能够留下姓名、电子邮件地址和简短的消息。恶意用户可以利用这
个机会插入简短消息之外的东西,比如对于其他用户不合适的图片或将用户重定向到另一个站点的 Javascrīpt,或者窃取 cookie 信息。 幸运的是,PHP 提供了 strip_tags() 函数,这个函数可以清除任何包围在 HTML 标记中的内容。strip_tags()
函数还允许提供允许标记的列表,比如 &b& 或 &i&。
浏览器内的数据操纵 有一类浏览器插件允许用户篡改页面上的头部元素和表单元素。使用 Tamper Data(一个 Mozilla
插件),可以很容易地操纵包含许多隐藏文本字段的简单表单,从而向 PHP 和 MySQL 发送指令。
用户在点击表单上的 Submit 之前,他可以启动
Tamper Data。在提交表单时,他会看到表单数据字段的列表。Tamper Data 允许用户篡改这些数据,然后浏览器完成表单提交。 让我们回到前面建立的示例。已经检查了字符串长度、清除了 HTML 标记并删除了十六进制字符。但是,添加了一些隐藏的文本字段,如下所示: 清单 17. 隐藏变量
&代码如下:
if ($_POST['submit'] == &go&){ //strip_tags
$name = strip_tags($_POST['name']);
substr($name,0,40);
//clean out any potential hexadecimal characters $name = cleanHex($name);
//continue processing&.
cleanHex($input){
$clean = preg_replace(&![\][xX]([A-Fa-f0-9]{1,3})!&,
&&,$input);
&form action=&&?php
echo $_SERVER['PHP_SELF'];?&& method=&post&&
for=&name&&Name&/label&
&input type=&text& name=&name& id=&name&
size=&20&P maxlength=&40&P/&&/p&
&input type=&hidden& name=&table&
value=&users&/&
&input type=&hidden& name=&action& value=&create&/& &input type=&hidden& name=&status& value=&live\&/& &p&&input type=&submit& name=&submit& value=&go&/&&/p& &/form&
注意,隐藏变量之一暴露了表名:users。还会看到一个值为 create 的 action
字段。只要有基本的 SQL 经验,就能够看出这些命令可能控制着中间件中的一个 SQL 引擎。想搞大破坏的人只需改变表名或提供另一个选项,比如 delete。 现在还剩下什么问题呢?远程表单提交。
远程表单提交
的好处是可以分享信息和服务。坏处也是可以分享信息和服务,因为有些人做事毫无顾忌。
以 表单为例。任何人都能够访问一个 Web 站点,并使用浏览器上的
File & Save As 建立表单的本地副本。然后,他可以修改 action 参数来指向一个完全限定的 URL(不指向
formHandler.php,而是指向
http://www.yoursite.com/formHandler.php,因为表单在这个站点上),做他希望的任何修改,点击
Submit,服务器会把这个表单数据作为合法通信流接收。
首先可能考虑检查
$_SERVER['HTTP_REFERER'],从而判断请求是否来自自己的服务器,这种方法可以挡住大多数恶意用户,但是挡不住最高明的黑客。这些人足够聪明,能够篡改头部中的引用者信息,使表单的远程副本看起来像是从您的服务器提交的。 处理远程表单提交更好的方式是,根据一个惟一的字符串或时间戳生成一个令牌,并将这个令牌放在会话变量和表单中。提交表单之后,检查两个令牌是否匹配。如果不匹配,就知道有人试图从表单的远程副本发送数据。 要创建随机的令牌,可以使用 PHP 内置的 md5()、uniqid() 和 rand() 函数,如下所示:
防御远程表单提交;可限制IP;&
&代码如下:
session_start();
($_POST['submit'] == &go&){
//check token
if ($_POST['token'] ==
$_SESSION['token']){
//strip_tags
$name = strip_tags($_POST['name']); $name = substr($name,0,40);
//clean out any potential hexadecimal
characters
$name = cleanHex($name);
//continue processing&.
}else{ //stop all processing! remote form posting attempt!
md5(uniqid(rand(), true));
$_SESSION['token']= $
cleanHex($input){
$clean = preg_replace(&![\][xX]([A-Fa-f0-9]{1,3})!&,
&&,$input);
&form action=&&?php
echo $_SERVER['PHP_SELF'];?&& method=&post&&
for=&name&&Name&/label&
&input type=&text& name=&name& id=&name&
size=&20&P maxlength=&40&P/&&/p&
&input type=&hidden& name=&token&
value=&&?php echo $?&&/&
&p&&input type=&submit&
name=&submit& value=&go&/&&/p&
这种技术是有效的,这是因为在 PHP 中会话数据无法在服务器之间迁移。即使有人获得了您的 PHP
源代码,将它转移到自己的服务器上,并向您的服务器提交信息,您的服务器接收的也只是空的或畸形的会话令牌和原来提供的表单令牌。它们不匹配,远程表单提交就失败了。

我要回帖

更多关于 php过滤特殊字符函数 的文章

 

随机推荐