要求在页面间传递一个验证字符串,
在生成页面的时候 随机产生一个字符串,
做为一个必须参数在所有连接中传递。同时将这个字符串保存在session中。
点连接或者表单进入页面后,判断session中的验证码是不是与用户提交的相同,如果相同,则处理,不相同则认为是重复刷新。
在处理完成后将重新生成一个验证码,用于新页面的生成
代码如下 | 复制代码 |
<?php |
ie6提交两次我也碰到过,大致是用图片代替submit时,图片上有个submit(),这样会提交两次,如果只是submit钮我没碰到过提交两次的情况。 现在整理一下:
方法基本上前面几位说得差不多
接收的页即2.php分为两部分,一部分处理提交过来的变量,一部分显示页面
处理变量完毕用header( "location: ".$_SERVER[ 'PHP_SELF '])跳转到自身页
本部分要做判断,如果没有post的变量就跳过。当然也可以跳到别的页面。
跳到别的页面返回时会有问题,建议做在一个php文件里。
如果上页穿过来得变量不符合要求可以强制返回 <script> history.go(-1); </script>
只说了一下大体思路,也许高手们不会遇到此类问题,可是并不是每个人都是高手。
代码如下 | 复制代码 |
if(isset($_POST)) |
也可以利用COOKIE
代码如下 | 复制代码 |
<?php |
session
主页面文件 index.php 代码:
代码如下 | 复制代码 |
<?php session_start(); ?> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>通过session禁止页面刷新</title> <style type="text/css"> <!-- .style1 { font-size: 14px; font-family: "华文仿宋"; font-weight: bold; } .style2 {font-family: "华文琥珀"} --> </style> </head> <body> <?php //使用文本存储数据 if($_SESSION[temp]==""){ if(($fp=fopen("counter.txt","r"))==false){ echo "打开文件失败!"; }else{ $counter=fgets($fp,1024); //读取文件中数据 fclose($fp); //关闭文本文件 $counter++; //计数器增加1 $fp=fopen("counter.txt","w"); //以写的方式打开文本文件 fputs($fp,$counter); //将新的统计数据增加1 fclose($fp); } //关闭文 //从文本文件中读取统计数据 if(($fp=fopen("counter.txt","r"))==false){echo "打开文件失败!";}else{ $counter=fgets($fp,1024); fclose($fp); echo "数字计数器: " .$counter ; } //输出访问次数 $_SESSION[temp]=1; //登录以后,$_SESSION[temp]的值不为空,给$_SESSION[temp]赋一个值1 }else{ echo "<script>alert('您不可以刷新本页!!'); history.back();</script>"; } ?> <table width="300" border="0" cellpadding="0" cellspacing="0" background="images/141.jpg"> <tr> <td height="35" align="center"><span class="style1">通过session禁止页面刷新</span></td> </tr> <tr> <td height="40" align="center"><span class="style2"> <?php if(($fp=fopen("counter.txt","r"))==false){echo "打开文件失败!";}else{ $counter=fgets($fp,1024); fclose($fp); echo "网页访问量: " .$counter ; } //输出访问次数?> </span></td> </tr> <tr> <td height="25" align="center"> </td> </tr> </table> </body> </html> |
counter.txt 文件为同目录下的记录登录数文件……
$counter=fgets($fp,1024); 为读取文件中 数值型值的方法(可包含小数点数值)……
具体用法
addslashes防止SQL注入
虽然国内很多PHP程序员仍在依靠addslashes防止SQL注入,还是建议大家加强中文防止SQL注入的检查。addslashes的问题在 于黑客 可以用0xbf27来代替单引号,而addslashes只是将0xbf27修改为0xbf5c27,成为一个有效的多字节字符,其中的0xbf5c仍会 被看作是单引号,所以addslashes无法成功拦截。
当然addslashes也不是毫无用处,它是用于单字节字符串的处理,多字节字符还是用mysql_real_escape_string吧。
另外对于php手册中get_magic_quotes_gpc的
举例:
代码如下 | 复制代码 |
或 <?php |
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
本函数将 unescaped_string 中的特殊字符转义,并计及连接的当前字符集,因此可以安全用于 mysql_query()。
Note: mysql_real_escape_string() 并不转义 % 和 _。
mysql_real_escape_string
Example#1 mysql_real_escape_string() 例子
代码如下 | 复制代码 |
<?php 以上例子将产生如下输出: Escaped string: Zak's and Derick's Laptop |
mysql_escape_string
本函数将 unescaped_string 转义,使之可以安全用于 mysql_query()。
注: mysql_escape_string() 并不转义 % 和 _。
本函数和 mysql_real_escape_string() 完全一样,除了 mysql_real_escape_string() 接受的是一个连接句柄并根据当前字符集转移字符串之外。mysql_escape_string() 并不接受连接参数,也不管当前字符集设定。
例子 1. mysql_escape_string() 例子
代码如下 | 复制代码 |
<?php |
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 不考虑。
我们可以利用判断来综合处理
代码如下 | 复制代码 |
function cleanuserinput($dirty){ if (get_magic_quotes_gpc()) { $clean = mysql_real_escape_string(stripslashes($dirty)); }else{ $clean = mysql_real_escape_string($dirty); } return $clean; } |
总结一下:
* addslashes() 是强行加;
* mysql_real_escape_string() 会判断字符集,但是对PHP版本有要求;
* mysql_escape_string不考虑连接的当前字符集。
下面针对常用表单特殊字符处理进行总结:
测试字符串:
代码如下 | 复制代码 |
$dbstr='D:test
|
测试代码:
代码如下 | 复制代码 |
header("Content-Type: text/html; charset=UTF-8"); $str = preg_replace("/s(?=s)/","\1",$str);//多个连续空格只保留一个 $str=stripslashes($str); |
字符串包含:反斜杠路径,单双引号,HTML标记、链接、未封堵的HTML标记,数据库语法容错,JS执行判断,PHP执行判断,多个连续回车换行符和空格。其中有些概念有包含关系
二、表单提交数据处理
1、强制加入反斜线
由于有些主机默认开启魔术引用get_magic_quotes_gpc,有些可能关闭,所以在程序上最好一律强制加入反斜线,这样可以统一处理,字符涉及单引号、双引号和反斜线。
代码如下 | 复制代码 |
function fnAddSlashes($data) |
2、对特殊字符处理
以下是几个常用字符串处理,可以视具体情况取舍。由于上面已经对提交表单数据进行一次转义,所以如果需要对内容替换或过滤需要考虑addslashes对相关字符的影响,替换或查找时需考虑反斜杠的添加。其它字符替换不影响,比如rn替换。
A、多个连续空格只保留一个
代码如下 | 复制代码 |
$data = preg_replace("/s(?=s)/","\1",$data );//多个连续空格只保留一个 |
B、回车换行替换成<br/>
代码如下 | 复制代码 |
$data = str_replace("r","<br/>",$data ); $data = str_replace("n","<br/>",$data ); |
//html中默认<br>没封堵,xhtml中<br/>有封堵,建议使用<br/>,更多区别:
C、多个连续<br/>只保留一个
代码如下 | 复制代码 |
$data = preg_replace("/((<br/?>)+)/i", "<br/>", $data );//多个连续<br/>标签只保留一个 |
D、全部过滤HTML标记
该方式是全部过滤潜在危险的标记,包括HTML、链接、未封堵HTML标记、JS、PHP。
使用函数strip_tags($data)
该函数使用后会过滤全部的HTML标记(包括链接)和PHP标记、JS代码等,其中链接会保留链接原文只是去除<a>标记和href部分内容,PHP标记和JS标记则会整体去除,包括中间的内容,如下图:
E、不过滤标记,只是把他们HTML化
该方法是把原提交内容全部按照普通文本来处理。
使用函数htmlspecialchars($data),该函数执行后会把提交数据全部按照普通文本来展示,如下图:
使用htmlentities函数执行结果(中文显示乱码):
三、写入数据库
由于使用addslashes($data)后对于高级的可信任用户可以直接写入数据库,但是addslashes无法拦截使用0xbf27代替的单引号,所以最好还是使用mysql_real_escape_string或mysql_escape_string进行转义,不过转义之前需先去除反斜杠(假设已默认开启addslashes)。
代码如下 | 复制代码 |
function fnEscapeStr($data) { if (get_magic_quotes_gpc()) $data=fnEscapeStr($data); |
PHP通用防注入安全代码
代码如下 | 复制代码 |
说明: 判断传递的变量中是否含有非法字符 如$_POST、$_GET 功能: 防注入 **************************/ //要过滤的非法字符 $ArrFiltrate=array(”‘”,”;”,”union”); //出错后要跳转的url,不填则默认前一页 $StrGoUrl=”"; //是否存在数组中的值 function FunStringExist($StrFiltrate,$ArrFiltrate){ foreach ($ArrFiltrate as $key=>$value){ if (eregi($value,$StrFiltrate)){ return true; } } return false; } //合并$_POST 和 $_GET if(function_exists(array_merge)){ $ArrPostAndGet=array_merge($HTTP_POST_VARS,$HTTP_GET_VARS); }else{ foreach($HTTP_POST_VARS as $key=>$value){ $ArrPostAndGet[]=$value; } foreach($HTTP_GET_VARS as $key=>$value){ $ArrPostAndGet[]=$value; } } //验证开始 foreach($ArrPostAndGet as $key=>$value){ if (FunStringExist($value,$ArrFiltrate)){ echo “alert(/”Neeao提示,非法字符/”);”; if (empty($StrGoUrl)){ echo “history.go(-1);”; }else{ echo “window.location=/”".$StrGoUrl.”/”;”; } exit; } } ?> |
/*************************
保存为checkpostandget.php
然后在每个php文件前加include(“checkpostandget.php“);即可
当然addslashes也不是毫无用处,它是用于单字节字符串的处理,多字节字符还是用mysql_real_escape_string吧。
打开magic_quotes_gpc来防止SQL注入
php.ini中有一个设置:magic_quotes_gpc = Off
这个默认是关闭的,如果它打开后将自动把用户提交对sql的查询进行转换,
比如把 ' 转为 '等,对于防止sql注射有重大作用。
如果magic_quotes_gpc=Off,则使用addslashes()函数
另外对于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 不考虑。
(1)mysql_real_escape_string -- 转义 SQL 语句中使用的字符串中的特殊字符,并考虑到连接的当前字符集
使用方法如下:
代码如下 | 复制代码 |
$sql = "select count(*) as ctr from users where username02.='".mysql_real_escape_string($username)."' and 03.password='". mysql_real_escape_string($pw)."' limit 1"; |
自定函数
代码如下 | 复制代码 |
|
总结一下:
* addslashes() 是强行加;
* mysql_real_escape_string() 会判断字符集,但是对PHP版本有要求;
* mysql_escape_string不考虑连接的当前字符集。
dz中的防止sql注入就是用addslashes这个函数,同时在dthmlspecialchars这个函数中有进行一些替换$string = preg_replace(/&((#(d{3,5}|x[a-fA-F0-9]{4}));)/, &1,这个替换解决了注入的问题,同时也解决了中文乱码的一些问题。
验证码识别一般分为以下几个步骤:
1. 取出字模
2. 二值化
3. 计算特征
4. 对照样本
代码如下 | 复制代码 |
$_img = imagecreatetruecolor($_width, $_height); $_white = imagecolorallocate($_img, 250, 250, 250); imagefill($_img, 0, 0, $_white); $_gray = imagecolorallocate($_img, 196, 196, 196); imagerectangle($_img, 0, 0, $_width-1, $_height-1, $_gray); for ($i=0; $i < 6; $i++) { for ($i=0; $i < 50; $i++) { for ($i=0; $i < $_code_length ; $i++) { header("Content-Type:image/png"); imagepng($_img); imagedestroy($_img); |
验证码使用方法
代码如下 | 复制代码 |
$getcode = $_POST['code']; if( $_SESSION["code"] = $getcode ) |