陈力:传智播客古代 珍宝币 泡泡龙游戏开发第46讲:PHP程序设计中的session应用实例

Session是服务器端技术, 可以把各自的数据放在各自的session中。本文实现了用Session实现购物车、防止非法用户登录、验证码、Cookie和Session的比较等功能。本节内容陈力:传智播客古代 珍宝币 泡泡龙游戏开发第46讲:PHP程序设计中的session应用实例

一、用Session实现购物车
    购物车实际给出界面,然后实现为后面讲解禁用cookie后还能使用session的知识点。


未禁用cookie时的程序设计代码:
MyHall.php
<?php
 //购物大厅
 echo "<h1>欢迎购买</h1>";
 echo "<a href='ShopProcess.php?bookid=sn001&bookname=天龙八部'>天龙八部</a><br/>";
 echo "<a href='ShopProcess.php?bookid=sn002&bookname=红楼梦'>红楼梦</a><br/>";
 echo "<a href='ShopProcess.php?bookid=sn003&bookname=西游记'>西游记</a><br/>";
 echo "<a href='ShopProcess.php?bookid=sn004&bookname=聊斋'>聊斋</a><br/>";
 echo "<hr/>";
 echo "<a href='ShowCart.php'>查看购买到的商品列表</a>";
?>
ShowProcess.php
<?php
 //接收用户购买请求,并把书保存到session中.
 $bookid=$_GET['bookid'];
 $bookname=$_GET['bookname'];
 //保存到session中
 session_start();
 $_SESSION[$bookid]=$bookname;
 echo "<br/>购买商品成功!";
 echo "<br/><a href='MyHall.php'>返回购物大厅继续购买</a>";
?>
ShowCart.php程序设计代码:
<?php
 echo "<h1>购物车商品有</h1>";
 session_start();
 foreach($_SESSION as $key=>$val){
  echo "<br/> 书号--$key 书名--$val";
 }
?>

再请思考一个问题?如果用户禁用cookie,防问的情况又会如何?

二、IE禁用Cookie后的session处理
    当用户禁用cookie后,服务器每次 session_start() 都会创建一个全新的seesion文件,后果就是无法让多个页面(phP程序)去共享同一份session文件。如何解决问题? 从cookie sessoin 和http协议入手解决。
     实验演示禁用Cookie后php共享数据导致的问题。此种情况下,客户浏览器访问时,服务器端也正常生成session文件,也返回session编号,但客户端浏览器无法接收,于是第二次访问时也不会自动传session给服务器。因此服务器又会为本次访问再创建一个session,即浏览器每次防问服务器都会产生文件,同一次会话会存在多份session文件,所以无法共享session文件。
    请问? 如果客户端禁用cookie,怎样实现session技术共享多个页面?
答: 
(1)在每个超链接上添加一个PHPSESSID=sesssionId;同时在每个页面加入:
if(isset($_GET[‘PHPSESSID’]){
 session_id($_GET[‘PHPSESSID’]); //设置sesssion_id
}
session_start();...
(2) 使用常量SID。使用方法如下:
在超链接 action  header(“Location: xx”) 可以直接拼接 SID常量即可。
echo "<a href='ShopProcess.php?bookid=sn003&bookname=西游记&".SID."'>西游记</a><br/>";
(3) 可以启用session.use_trans_sid 指定是否启用透明 SID 支持。即可以这样设置ssssion. use_trans_sid = 1,这样重启apache即可生效。
    考虑CookIE被禁用时的程序设计代码:
MyHall.php源程序设计代码:
<?php
 if(isset($_GET['PHPSESSID'])){
  session_id($_GET['PHPSESSID']); //取得PHPSESSID
 }
 session_start();
 //echo "sid====".SID;
 //购物大厅
 echo "<h1>欢迎购买</h1>";
 echo "<a href='ShopProcess.php?bookid=sn001&bookname=天龙八部&".SID."'>天龙八部</a><br/>";
 echo "<a href='ShopProcess.php?bookid=sn002&bookname=红楼梦&".SID."'>红楼梦</a><br/>";
 echo "<a href='ShopProcess.php?bookid=sn003&bookname=西游记&".SID."'>西游记</a><br/>";
 echo "<a href='ShopProcess.php?bookid=sn004&bookname=聊斋&".SID."'>聊斋</a><br/>";
 echo "<hr/>";
 echo "<a href='ShowCart.php?".SID."'>查看购买到的商品列表</a>";
?>
ShowCart.php:
<?php
 echo "<h1>购物车商品有</h1>";
 //这里不能让服务器创建一个新的session
 if(isset($_GET['PHPSESSID'])){
  session_id($_GET['PHPSESSID']);
 }
 session_start();
 foreach($_SESSION as $key=>$val){
  echo "<br/> 书号--$key 书名--$val";
 }
?>
ShopProcess.php程序设计源代码,接收用户购买请求,并把书保存到session中。
<?php
 //接收用户购买请求,并把书保存到session中。
 //保存到session中
 if(isset($_GET['PHPSESSID'])){
  session_id($_GET['PHPSESSID']);
 }
 session_start();
 $bookid=$_GET['bookid'];
 $bookname=$_GET['bookname'];
 $_SESSION[$bookid]=$bookname;
 echo "<br/>购买商品成功!";
 echo "<br/><a href='MyHall.php?".SID."'>返回购物大厅继续购买</a>";
?>

三、防止用户非法登录到某个页面
     要求用户必须登录后,才能操作管理页面。
     *测试的时候,先直接访问manage.php,不能登录,然后正确方式登录即可。
     要求用array来充当数据库(可以直接指定用户名和密码来完成),完成模拟验证。
****login.php****
<html>
<body>
<form action="logincl.php" method="post">
u:<input type="text" name="username"/><br/>
p:<input type="password" name="pwd"/><br/>
<input type="submit" value="登录"/>
</form>
<?php 
 $info=$_REQUEST["info"];
 echo $info;
?>
</body>
</html>
***logincl.php****
<?php 
 $username=$_POST["username"];
 $pwd=$_POST["pwd"];
 if($username=="shun"&&$pwd=="123"){
  //合法
  session_start();
  $_SESSION['logininfo2'] = $username;
  header("Location: manage.php");
 }else{
  header("Location: login.php");
 }
?>
*****manage.php******
<?php 
  //合法
  session_start();
  $username=$_SESSION["logininfo2"];
  if($username==null||$username==""){
   header("Location: login.php?info=请您登录再进入管理界面");
   return ;
  }
?>
<html>
<body>
<h1>管理系统界面 ,欢迎您!</h1>
</body>
</html>

如何防止用户非法登录案例2:在雇员管理系统中防止非法用户登录。
在loginProcess.php代码中增加:
if($name!=""){
  //把登陆信息写入cookie 'loginname':$name
  //把登陆表 把登陆的人ip id..
  //合法
  session_start();
  $_SESSION['loginuser']=$name;
  header("Location: empManage.php?name=$name"); 
  exit();
 }
    在编写commmon.php文件中添加了一个函数
 function checkUserValidate(){//把验证用户是否合法封装函数
  session_start();//先写在封
  if(empty($_SESSION['loginuser'])){
   header("Location: login.php?errno=1");
  }
 }
    在需要防止用户非法登录页面中引入这样两句(这两句放在页面的开头)。
require_once 'common.php';
 checkUserValidate();

四、用户登录时验证输入的验证码是否正确 
(1)一次性验证码的主要目的就是为了限制人们利用工具软件来暴力猜测密码。 
(2)服务器程序接收到表单数据后,首先判断用户是否填写了正确的验证码,只有该验证码与服务器端保存的验证码匹配时,服务器程序才开始正常的表单处理流程。
为什么我们需要验证码:防止登录时恶意攻击,防止灌水。

请在我们的雇员管理系统添加验证码功能。
checkCode.php 这个文件引入到你的项目中,在login.php页面中添加一个<img />标签,向checkCode.php发送请求。
<img src="checkCode.php" οnclick="this.src='checkCode.php?aa='+Math.random()"/>
在loginProcess.php 页面中,添加对验证码的处理代码。
//先看看验证码是否 ok
session_start();
if($checkCode!=$_SESSION['myCheckCode']){
header("Location: login.php?errno=2");
exit();
}
checkCode.php源代码:
<?php
// echo rand(2,9);
// echo "<br/>".dechex(rand(1,15))."<br/>";
 session_start();
 $checkCode="";
 for($i=0;$i<4;$i++){
  $checkCode.=dechex(rand(1,15));
 }
 //讲随机验证码保存到session中
 $_SESSION['myCheckCode']=$checkCode;
 //创建图片,并把随机数画上去
 $img=imagecreatetruecolor(110,50);
 //背景默认就是黑色
 //你可以指定背景颜色
 $bgcolor=imagecolorallocate($img,0,0,0);
 imagefill($img,0,0,$bgcolor);
 //创建新的颜色
 $white=imagecolorallocate($img,255,255,255);
 $blue=imagecolorallocate($img,0,0,255);
 $red=imagecolorallocate($img,255,0,0);
 $green=imagecolorallocate($img,255,0,0);
 //画出干扰线段
 for($i=0;$i<20;$i++){
  /*switch(rand(1,4)){
   case 1:
    imageline($img,rand(0,110),rand(0,30),rand(0,110),rand(0,30),$green);
    break;
   case 2:
    imageline($img,rand(0,110),rand(0,30),rand(0,110),rand(0,30),$blue);
    break;
   case 3:
    imageline($img,rand(0,110),rand(0,30),rand(0,110),rand(0,30),$green);
    break;
   case 4:
    imageline($img,rand(0,110),rand(0,30),rand(0,110),rand(0,30),$red);
    break;
  }*/
  //更好的方法是颜色随机
  imageline($img,rand(0,110),rand(0,30),rand(0,110),rand(0,30),imagecolorallocate($img,rand(0,255),rand(0,255),rand(0,255)));
 }
 //画出噪点,自己画.
 //for($i=0;$i<10;
 //把四个随机值画上去
 imagestring($img,rand(1,5),rand(2,80),rand(2,10),$checkCode,$white);
 //如果要使用中文
 //array imagefttext (  string $font_file , string $text [, array $extrainfo ] )
 //imagettftext($img,15,10,20,25,$white,"STXINWEI.TTF","北京你好");
 //输出
 header("content-type: image/png");
 imagepng($img);
?>

五、雇员管理系统网站(3.0)
    在这一讲的雇员管理系统中添加如下功能:
version3.0 新增加的功能:
 1:  显示上一次用户登录时间
 2:  防止用户非法登录到管理界面
知识点:
 1.cookie技术
 2.session技术
 3.框架图分析程序的技巧

六、cookie 和 session比较
1:存在的位置
cookie保存在客户端,session保存在服务器端的文件系统/数据库/memcache。
2:安全性
比较而言cookie的安全性比session要弱。
3:网络传输量
cookie通过网络在客户端与服务器端传输。而session保存在服务器端,不需要传输。


4:生命周期(以20分钟为例)
cookie的生命周期是累计的,从创建时就开始计时,20分钟后cookie生命周期结束,cookie就无效。session的生命周期是间隔的,从创建时开始计时如在20分钟,没有访问过 session,那么session信息无效,如果在20分钟内,比如第19分钟时,访问过session,那么,它的生命周期将重新开始计算。
测试:需要把session.gc_maxlifetime时间设置长些,然后测试。
 session.cookie_lifetime =0时,发现每访问一次就会更新对应的session文件。
 session.cookie_lifetime 小于 session.gc_maxlifetime 就会 当 session.cookie_lifetime 时间到时候,会生成一个新的session文件,原来的session文件将成为垃圾(待gc回收)。

七、php.ini 中关于cookie和session配置说明(重点难点)
session.name =名字
说明:Name of the session (used as cookie name)
session.use_trans_sid = 0 说明:给每个url启用 session名=sessionId,对安全有影响,不推荐开启。
session.save_path =“c:/mysession”说明:session保存路径。
下面三个是一组,用于控制session文件存在时间:
session.gc_maxlifetime = 1440说明:session默认最大生命周期。
session.gc_probability = 1 
session.gc_divisor = 1000

通过创建三个文件来依次说明各个配置信息的含义:
a.php –创建session,并写入数据。
<?php //创建session
 session_start();
 //输出当前用户session的信息
 echo "session名字=".session_name()." --session id=".session_id();
 //保存session信息。
 $_SESSION['name']="司马相如";
 $_SESSION['pwd']="123";
 echo "<br/>向sesion中放入的信息是= name=司马相如 pwd=123";
?>
b.php –从session中读取数据
<?php 
 //获取session信息
 session_start();
 //输出当前用户session的信息
 echo "session名字=".session_name()." --session id=".session_id();
 echo "<br/>从当前用户session数组中取出信息=<br/>";
 print_r($_SESSION);
?>
c.php –删除当前session数据(文件本身删除有gc完成)
<?php //销毁当前用户session
 session_start();
 $_SESSION=array();
 //如果是基于cookie的session(这里也可以不用判断,直接销毁.与session相关的cookie)
 //if(isset($_COOKIE[session_name()])){
  setCookie(session_name(),'',time()-100,"/");
 //}
 session_destroy();
 //输出当前用户session的信息
 echo "session名字=".session_name()." --session id=".session_id();
 echo "<br/>从当前用户session数组中取出信息=<br/>";
 print_r($_SESSION);
?>

八、session.name 案例
    通过httpwatch抓取信息说明, session.use_trans_sid。session.save_path 可以通过修改路径运行 a.php。
session.gc_maxlifetime:打开关闭ie 三次访问 a.php,会创建三个session文件,然后让最后开的a.php去做测试。
说明:
① gc 启动的时间是 session_start(). 但是其启动的概率 pro/divi,它的主要作用就是去,删除已经过期的sessoin文件。(达到maxlifetime时间)。
② 当前浏览器对应的session对应文件即使达到maxlifetime也不会被删除。因为发送了cookie_id服务器认为你还要使用(真正的原因是会更新该浏览器对应的session文件时间。所以gc认为这个文件没有到期),所以不删除。
③ 只要某个session文件被操作,它的时间就会被更新。
④ (但是这样有新的问题,就是如果我们希望一个用户打开浏览器后,在30s没有任何动作但是没有关闭浏览器,就重新登录【怎么办?】)
通过修改 session.cookie_lifetime=30 来处理, 这样就会让本浏览器的session到30s后也销毁(我测试了session内容没有,但是文件还在!!!)
session保存的位置:
① 本机某个文件 或者数据库,如果session 数据量大同时有要求速度快我们推荐使用memcache技术。
② 远程保存到别的机器 (linux 下可以使用 nfs[网络文件系统] 或者 samba,如果是windows下可以使用共享文件夹的方式)。

说明:当某个用户操作session的时候,会使用到session_start(),该函数会调用gc,但是其概率是session.gc_probability/ session.gc_divisor 
原因是: 对于一个网站说,有很多用户访问,因此当大量用户访问的时候,概率很多. 如果网站的规模越大,我们建议把这个概率设置越小。

演示
session.gc_maxlifetime = 30 
说明:session默认最大生命周期
session.gc_probability = 1000 
session.gc_divisor = 1000

session.cookie_lifetime= 0 该设置可以指定cookie默认生命周期,默认是0,表示当关闭浏览器后,该cookies失效,你可以这样:
setcookie(“名字”,”val”,time()+3600);
setcookie(“名字”,”val”);

session.use_cookies =1说明:是否使用cookie
session.cookie_path = /说明:The path for which the cookie is valid. 删除时要对应。
session.domain_name = 说明:根据规范产生域名,自动生成,无需设置。
session.cookie_lifetime= 0 说明:cookie保存时间。默认0,关闭浏览器就失效。

九、自定义会话处理器
    需求:为什么session文件打头是sess_*,我们能不能自己定义session文件名? 我们能不能把session信息高效的保存到memcache中。这里我们就需要对php 技术对session处理的机制做更加深入的了解。
session.save_handler = files [user|memcache]说明:session 使用何种方式存取.
Handler used to store/retrieve data 。

** session.save_handler = user 要和 session_set_save_handler() 函数配合使用。
***a1.php*******
<?php 
 //创建session
 //session_start();
 //使用自定义session处理器来搞定
 require_once "session.php";
 //输出当前用户session的信息
 echo "session名字=".session_name()." --session id=".session_id();
 //保存session信息.
 $_SESSION['name']="司马相如";
 $_SESSION['pwd']="123";
 echo "<br/>向sesion中放入的信息是= name=司马相如 pwd=123";
?>
***b1.php*******
<?php 
 //获取session信息
 //session_start();
 //使用自定义session处理器来搞定
 require_once "session.php";
 //输出当前用户session的信息
 echo "session名字=".session_name()." --session id=".session_id();
 echo "<br/>从当前用户session数组中取出信息=<br/>";
 print_r($_SESSION);
?>
***c1.php*******
<?php 
 //销毁当前用户session
 //session_start();
 //使用自定义session处理器来搞定
 require_once "session.php";
 $_SESSION=array();
 //如果是基于cookie的session(这里也可以不用判断,直接销毁.与session相关的cookie)
 //if(isset($_COOKIE[session_name()])){
  setCookie(session_name(),'',time()-100,"/");
 //}
 session_destroy();
 //输出当前用户session的信息
 echo "session名字=".session_name()." --session id=".session_id();
 echo "<br/>从当前用户session数组中取出信息=<br/>";
 print_r($_SESSION);
?>
***session.php****
<?php 
//session_start()
function open($save_path, $session_name)
{
  //把从php.ini读取的$save_path设置成全局变量,供其它函数使用。
  global $sess_save_path;
  $sess_save_path = $save_path;
  return(true);
}
//session_write_close() session_destory()
function close()
{
  return(true);  //一般就是返回true;
}
//session_start() $_SESSION
function read($id)
{
  //首先要获取open函数设置的 session保存路径。
  global $sess_save_path;
  //将该session文件的全路径获取
  $sess_file = "$sess_save_path/my_$id";
    return (string) @file_get_contents($sess_file); //从文件中取出。
}
//session_write_close() 提交$SESSION数据
function write($id, $sess_data)
{
  //如果是写,则根据用户的配置来实际存放。
  global $sess_save_path;
  $sess_file = "$sess_save_path/my_$id";
  if ($fp = @fopen($sess_file, "w")) {
    $return = fwrite($fp, $sess_data);
    fclose($fp);
    return $return;
  } else {
    return(false);
  }
}
//session_destory()
function destroy($id)
{
  global $sess_save_path;
  $sess_file = "$sess_save_path/my_$id";
  return(@unlink($sess_file));
}
//session进行垃圾回收时
function gc($maxlifetime)
{
  global $sess_save_path;
  //将到期的session.
  foreach (glob("$sess_save_path/my_*") as $filename) {
    if (filemtime($filename) + $maxlifetime < time()) {
      @unlink($filename);
    }
  }
  return true;
}
session_set_save_handler("open", "close", "read", "write", "destroy", "gc");
session_start();
// proceed to use sessions normally
?>

【推荐阅读】陈力:传智播客古代 珍宝币 泡泡龙游戏开发第46讲:PHP程序设计中的session应用实例

陈力:传智播客古代 珍宝币 泡泡龙游戏开发第46讲:PHP程序设计中的session应用实例相关推荐

  1. 陈力:传智播客古代 珍宝币 泡泡龙游戏开发第50讲:PHP中的xml编程

    陈力:传智播客古代 珍宝币 泡泡龙游戏开发第50讲:PHP中的xml编程 Xml是extensiable markup language的简称,包括文档声明.元素.属性.注释.CDATA区.特殊字符 ...

  2. 陈力:传智播客古代 珍宝币 泡泡龙游戏开发第51讲:PHP中smarty模板技术介绍

    陈力:传智播客古代 珍宝币 泡泡龙游戏开发第51讲:PHP中smarty模板技术介绍 smarty模板技术PHP程序设计中必须掌握的知识,本文结合贵阳网站建设中的案例介绍了基于smarty技术的员工列 ...

  3. 陈力:传智播客古代 珍宝币 泡泡龙游戏开发第40讲:PHP中预定义超全局变量

    陈力:传智播客古代 珍宝币 泡泡龙游戏开发第40讲:PHP中预定义超全局变量 超全局变量是在全部作用域中始终可用的内置变量.PHP 中的许多预定义变量都是"超全局的".PHP供提供 ...

  4. 陈力:传智播客古代 珍宝币 泡泡龙游戏开发第35讲:PHP 抽象类与接口

    陈力:传智播客古代 珍宝币 泡泡龙游戏开发第35讲:PHP 抽象类与接口 如果一个类使用abstract 来修饰,则该类就是抽象类.抽象方法是声明为abstract的,是不需要实现的,供子类继承且实现 ...

  5. 陈力:传智播客古代 珍宝币 泡泡龙游戏开发第22讲:PHP语法、数据类型(整型、布尔型、浮点型、字符串型)

    陈力:传智播客古代 珍宝币 泡泡龙游戏开发第22讲:PHP语法.数据类型(整型.布尔型.浮点型.字符串型) PHP语法是什么样的,有哪些数据类型,有些什么变量.本文对PHP语法.数据类型(整型.布尔型 ...

  6. 陈力:传智播客古代 珍宝币 泡泡龙游戏开发第48讲:PHP绘图技术

    陈力:传智播客古代 珍宝币 泡泡龙游戏开发第48讲:PHP绘图技术 php绘图坐标体系中,坐标原点位于左上角,以像素为单位.php绘图时,要创建画布.画出各种图形.输出图形.销毁图形(释放内存资源). ...

  7. 陈力:传智播客古代 珍宝币 泡泡龙游戏开发第26讲:PHP函数

    陈力:传智播客古代 珍宝币 泡泡龙游戏开发第26讲:PHP函数 什么是PHP函数,如何通过function定义一个函数,如何理解函数的调用过程.这些问题都是网站建设中经常遇到的程序设计问题.在进行网站 ...

  8. 陈力:传智播客古代 珍宝币 泡泡龙游戏开发第28讲:PHP数组

    陈力:传智播客古代 珍宝币 泡泡龙游戏开发第28讲:PHP数组 PHP程序设计语言中的数组如何创建,一维数组的引用,PHP数组变量,foreach语句,如何对数组进行排序等等知识都是贵阳网站建设中的主 ...

  9. 陈力:传智播客古代 珍宝币 泡泡龙游戏开发第30讲:PHP多维数组

    陈力:传智播客古代 珍宝币 泡泡龙游戏开发第30讲:PHP多维数组 在PHP程序设计语言中,如何创建二维数组呢,怎样使用二维数组,这些问题在网站建设中非常重要.二维数组的基本语法为: $a=array ...

最新文章

  1. 体检系统前端源码_给您的前端进行健康检查
  2. 在R.java中新建自定义的新类
  3. 第一行代码学习笔记第四章——探究碎片
  4. 剑指offer--不用加减乘除做加法
  5. socket的阻塞模式和非阻塞模式(send和recv函数在阻塞和非阻塞模式下的表现)
  6. SQL:如何用一个sql统计出全校男生个数、女生个数以及总人数
  7. phalcon的一些中文手册和帮助文档地址收集
  8. linux 文件可执行_深入理解linux内核——可执行文件执行过程(2)
  9. 【转】Unity3D研究院之设置自动旋转屏幕默认旋转方向
  10. shell命令wc,md5sum,basename
  11. 十大排序算法——堆排序(C语言)
  12. 高等数学(第七版)同济大学 习题1-2 个人解答
  13. 招投标工作中投标书编制的流程是怎样的?
  14. 【菜鸟C++学习杂记】ASCII码转换和显示
  15. UML用例图-软件需求分析与设计(很详细,很详细,很详细)
  16. Git学习笔记之时光穿梭机
  17. 华为要开发人工智能手机 魅族新机发布会却被调侃不用开了!
  18. 流畅的python第二章, 列表和元组和数组
  19. Midjourney如何给模特换衣服
  20. UI 优先的统一身份认证系统 Casdoor

热门文章

  1. houdini之blast
  2. 防火墙内外网隔离实例
  3. dll依赖查看工具Depends
  4. 键盘按键修改工具(修改默认按键位置) 绿色版
  5. SAXReader简单的解析xml文件
  6. 戴尔服务器修改分辨率,戴尔Windows Vista 中设置显示分辨率的方法
  7. pinia 介绍与安装
  8. Python查看源码
  9. 经纬度坐标与实际距离的计算转换
  10. 2019学硕计算机分数,2019计算机考研408分数要求以及复习攻略?