会话
-
用户打开浏览器,点击网站中的多个超链接,访问服务器的多个web资源,然后关闭浏览器,整个过程称为会话。
-
每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自会产生一些数据,服务器要想办法为每个用户保存这些数据。(多个用户点击超链接通过一个php购买了商品,服务器应该想办法把每一个用户购买的商品保存在各自的地方,以便于这些用户点结账php时,可以分开来为用户结账。)
-
如何解决?
- 加数据库表:用户账号,商品号,数量(用户账号,商品号作为主键)
- 会话技术
-
为什么一些软件和网站会推荐你浏览过的视频和商品等等?
-
为什么你登录某个邮箱时会显示你上次登录的时间?
-
为什么保证用户在一定时间内不用登录?
cookie
-
cookie客户端技术,服务器把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据。这样web资源处理的就是用户各自的数据。
-
cookie保存在客户端。
-
原理图
-
服务器在客户端保存用户的信息,比如登录名,密码等…就是cookie。这些信息数据量并不大(因为是写入用户磁盘的),服务器端在需要的时候可以从客户端读取,保存在客户端的浏览器缓存目录下。
-
作用
- 保存上次登录时间等信息
- 保存用户名和密码,在一定时间不用重新登录
- 更换网站背景色,背景音乐等
cookie基本使用
- 如果没有提供第三个参数(时间长度),cookie不会保存到客户端,当浏览器会话结束cookie就失效。
<?php
//创建cookie信息
//将用户名和密码保存到客户端的cookie
//setCookie(key[名字],val[值],cookie值[在客户端保存的时间,按秒计算])函数用于保存cookie信息
setCookie("name","大傻子",time()+12000);
setCookie("password","123456",time()+12000);
echo "save success";
?>
- 使用HttpWatch抓包:当浏览器访问setCookie.php页面时,我们的服务器就会以Set-Cookie: name=%E5%A4%A7%E5%82%BB%E5%AD%90; expires=Thu, 13-Dec-2018 05:56:18 GMT; Max-Age=12000
Set-Cookie: password=123456; expires=Thu, 13-Dec-2018 05:56:18 GMT; Max-Age=12000回送http响应,当浏览器获取到该信息后,就会保存相应的cookie。
- bool setCookie(string $name[,string $value[,int $expire=0[,string $path]]]),说明我们只能保存字符串类型。
参数 | 说明 | 举例 |
---|---|---|
name | cookie的名字 | 使用$COOKIE[‘cookiename’]调用名为cookiename的cookie |
value | cookie的值,保存在客户端,如果用来保存敏感数据,用md5加密 | 假定name是‘cookiename’,$COOKIE[‘cookiename’]取得其值 |
expire | cookie过期的时间。这是个unix时间戳,即从unix纪元开始的秒数。通常用time()+秒数来设定cookie的失效期,用time()-秒数来删除cookie | time()+606024*30将设定cookie30天后失效。如果未设定,cookie将会在会话结束后失效 |
path | cookie在服务器端的有效路径 | 默认是当前路径 |
domain | 该cookie有效的域名 | |
secure | 指定cookie是否通过安全的https连接传送。设置为true,cookie仅在安全的链接中被设置。默认为false | 0或1 |
- 读取cookie值:使用全局数组$_COOKIE(若保存时间到期,则不能取出cookie值)
<?php
echo "<pre>";
print_r($_COOKIE);
echo "</pre>";
//取值
if(!empty($_COOKIE['name'])){
$name=$_COOKIE['name'];
echo $name."<br/>";
}else{
echo "名字为空";
}
if(!empty($_COOKIE['password'])){
$password=$_COOKIE['password'];
echo $password;
}else{
echo "密码为空";
}
?>
- 客户端可以保存多个cookie值,时间长度自行设置,无需一致。
- 对中文进行urlencode编码。
- 客户端的cookie信息是通过http协议传送给服务器的。
更新cookie信息
- 将之前的值覆盖即可。
<?php
setCookie("password","456789",time()+3000);
?>
删除cookie信息
- 指定删除某个cookie值
<?php
//要删除某个key,使用time()-秒数
setCookie("password","",time()-300);
?>
- 删除所有的cookie值
<?php
foreach($_COOKIE as $key=>$val){
//要删除某个key,使用time()-秒数
setCookie($key,"",time()-200);
}
?>
显示用户上次的访问时间
- 用户第一次访问则显示第一次访问,后续访问显示上一次的访问时间。
<?php
//看看有没有上次访问的时间
if(!empty($_COOKIE['lastVisit'])){
echo "你上次登录时间是".$_COOKIE['lastVisit'];
//更新时间
setcookie("lastVisit",date("Y-m-d H:i:s"),time()+24*60*60*30);
}else{
//第一次登陆
echo "第一次访问";
setcookie("lastVisit",date("Y-m-d H:i:s"),time()+24*60*60*30);
}
?>
问题
- 安全性问题:对于我们所编写的学生管理系统,当我们直接访问admin.php页面,可以直接管理学生信息,多么可怕!!!
- 张三和李四在淘宝网各自添加了自己喜欢的商品,因而他们各自购物车中的商品不一样,如何实现?
- 不同的用户登录网站后,不管该用户浏览该网站的哪个页面,都有显示登录人的名字,同时可以随时去查看自己的购物车中的商品。如何实现?
- 数据库实现:设计表,每访问一次页面,与数据库进行一次交互,代价过高。
- 用cookie实现:cookie值存在客户端(安全性不高),网络传数据(带宽问题)。
- 用session实现
session
- session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session文件(服务器磁盘),由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其他web资源时,其他web资源再从用户各自的session中取出数据为用户服务。
- session文件被一个浏览器独自访问。
- 原理
session的基本使用
- 不管是保存session数据,还是获取,删除session数据,都必须先初始化session。
- session文件中可以存放多个key=>val对。
- 保存session数据,中文还是以中文保存,不进行编码。
- session数据默认存在时间为1440s(24min),可以在php.ini中设置。
session.gc_maxlifetime = 1440
- session数据存放的路径可以修改(修改完成后重启apache)。
session.save_path = "/tmp"
- session文件中可以保存string,double,int,bool,array,object类型
<?php
//保存session数据
//初始化session
session_start();
//保存数据
$_SESSION['name']="大傻子";
//session文件中可以保存double,int,bool,array,object类型
$arr1=array("大撒","的撒","定位");
$_SESSION['arr1']=$arr1;
echo "save sucess";
?>
- 保存的内容:
- name|s:9:“大傻子”;arr1|a:3:{i:0;s:6:“大撒”;i:1;s:6:“的撒”;i:2;s:6:“定位”;}
获取session数据
- 不管是保存session数据,还是获取session数据,都必须先初始化session。
<?php
session_start();
echo "<pre>";
print_r($_SESSION);
echo "</pre>";
?>
- 此时,当我们用google浏览器获取session数据时,session数据为空。
- 获取指定session数据
//通过key来获取指定session值
echo "name=".$_SESSION['name']."<br/>";
$arr1=$_SESSION['arr1'];
foreach($arr1 as $key=>$val){
echo $val."<br/>";
}
- 如果我们要取出对象,则需要事先声明一下类的定义信息(require_once ‘**.class.php’)。
更新session数据
session_start();
//保存数据
$_SESSION['name']="二傻子";
echo "update sucess";
删除session数据
- unset(…)函数删除某个session数据。
- session_destroy();删除所有session数据。
<?php
session_start();
//删除某个session数据
unset($_SESSION['name']);
//删除所有的session数据
session_destroy();
echo "<pre>";
print_r($_SESSION);
echo "</pre>";
?>
cookie和session
- 在web开发中,服务器可以为每个用户浏览器创建一个超全局变量$_SESSION,注意:一个浏览器独占一个$_SESSION。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session文件中,当用户使用浏览器访问其他php页面时,其他php页面可以从用户的$_SESSION中取出该用户的数据,为用户服务。
- cookie是把用户的数据写给用户的浏览器。
- 在使用$_SESSION前要保证session被初始化:
session_start();
//不推荐将php.ini中的session.auto_start设置为1,影响效率
//session.auto_start=1;
- 为什么浏览器的一次会话(访问多个页面)会访问同一个session文件?
session实际案例
-
购物车实例
-
shopping.php(购物界面)
<html>
<head>
<title>购物网站</title>
</head>
<body>
<?php
echo "<h1>购买菜单</h1>";
echo "<table border=1px width=200px>";
echo "<tr><th>红楼梦</th><th><a href='process.php?bookId=sn001&bookName=红楼梦'>购买</a></th></tr><br/>";
echo "<tr><th>水浒传</th><th><a href='process.php?bookId=sn002&bookName=水浒传'>购买</a></th></tr><br/>";
echo "<tr><th>三国演义</th><th><a href='process.php?bookId=sn003&bookName=三国演义'>购买</a></th></tr><br/>";
echo "<tr><th>西游记</th><th><a href='process.php?bookId=sn004&bookName=西游记'>购买</a></th></tr><br/>";
echo "</table>";
echo "<h1><a href='shoppingCart.php'>到购物车查看</a></h1>";
?>
</body>
</html>
- process.php(session数据保存)
<?
session_start();
if(isset($_GET['bookId']) && isset($_GET['bookName'])){
$bookId=$_GET['bookId'];
$bookName=$_GET['bookName'];
$_SESSION[$bookId]=$bookName;
//echo "<pre>";
//print_r($_SESSION);
//echo "</pre>";
echo "<h1><a href='shopping.php'>购买成功,返回购买菜单继续购买</a></h1>";
echo "<h1><a href='shoppingCart.php'>购买成功,到购物车查看</a></h1>";
}
?>
- shoppingCart.php(购物车)
<?php
echo "<h1>购物车</h1>";
session_start();
echo "<table border=1px>";
foreach($_SESSION as $key=>$val){
echo "<tr><th>$key</th><th>$val</th></tr>";
}
echo "</table>";
?>
禁用cookie
- 禁用cookie后,服务器每次session_start()都会创建一个全新的session文件,后果就是无法让多个页面共享同一份session文件(PHPSESSID会生成多个,即会生成多个文件)。
- 客户端禁用cookie,怎样实现session技术共享多个页面(禁用cookie后,可以自行传递PHPSESSID,方法虽然笨拙但可实现效果。)?
- 方法一:设置session_id。在每个超链接上添加PHPSESSID=$id,同时将每个页面启动session_start();语句修改为:
if(isset($_GET['PHPSESSID'])){
//设置session_id:如果设置了session_id,则启用已有的session文件,否则启动新的session文件
session_id($_GET['PHPSESSID']);
}
session_start();
$sid=session_id();
- shopping.php(购物界面)
<html>
<head>
<title>购物网站</title>
</head>
<body>
<?php
if(isset($_GET['PHPSESSID'])){
session_id($_GET['PHPSESSID']);
}
session_start();
$sid=session_id();
echo "<h1>购买菜单</h1>";
echo "<table border=1px width=200px>";
echo "<tr><th>红楼梦</th><th><a href='process.php?bookId=sn001&bookName=红楼梦&PHPSESSID=$sid'>购买</a></th></tr><br/>";
echo "<tr><th>水浒传</th><th><a href='process.php?bookId=sn002&bookName=水浒传&PHPSESSID=$sid'>购买</a></th></tr><br/>";
echo "<tr><th>三国演义</th><th><a href='process.php?bookId=sn003&bookName=三国演义&PHPSESSID=$sid'>购买</a></th></tr><br/>";
echo "<tr><th>西游记</th><th><a href='process.php?bookId=sn004&bookName=西游记&PHPSESSID=$sid'>购买</a></th></tr><br/>";
echo "</table>";
echo "<h1><a href='shoppingCart.php'>到购物车查看</a></h1>";
?>
</body>
</html>
- process.php(session数据保存)
<?
if(isset($_GET['PHPSESSID'])){
session_id($_GET['PHPSESSID']);
}
session_start();
$sid=session_id();
if(isset($_GET['bookId']) && isset($_GET['bookName'])){
$bookId=$_GET['bookId'];
$bookName=$_GET['bookName'];
$_SESSION[$bookId]=$bookName;
echo "<pre>";
print_r($_SESSION);
echo "</pre>";
echo "<h1><a href='shopping.php?PHPSESSID=$sid'>购买成功,返回购买菜单继续购买</a></h1>";
echo "<h1><a href='shoppingCart.php?PHPSESSID=$sid'>购买成功,到购物车查看</a></h1>";
}
?>
- shoppingCart.php(购物车)
<?php
if(isset($_GET['PHPSESSID'])){
session_id($_GET['PHPSESSID']);
}
session_start();
$sid=session_id();
echo "<h1>购物车</h1>";
echo "<table border=1px>";
foreach($_SESSION as $key=>$val){
echo "<tr><th>$key</th><th>$val</th></tr>";
}
echo "</table>";
echo "<h1><a href='shopping.php?PHPSESSID=$sid'>购买成功,返回购买菜单继续购买</a></h1>";
?>
- 方法二:使用SID(常量),值为[PHPSESSID=id号]
- 方法三:session.use_trans_sid指定是否启用透明SID支持,默认为0。设置session.use_trans_sid=1,然后重启apache。
防止用户非法登录到某个页面
- 例如:用户必须先执行登录页面,才能去管理相关信息。
- 在用户登录界面将用户的信息保存到session文件中,若有人想直接访问管理界面,看是否有session文件或者session文件中是否含有用户信息?若没有,则为非法用户;若有,则直接进。
验证码
- 防止登录时恶意攻击,防止灌水…
- 启用画图,重启apache。
extension=gd2
- 将验证码填入图片,在进行交互时,传图片,则无法得到图片中的内容。
<?php
//session_start();
$checkCode="";
for($i=0;$i<4;++$i){
//dechex十进制转十六进制,因此生成的是数字和字母的组合
$checkCode.=dechex(rand(1,15));
}
//$_SESSION['checkCode']=$checkCode;
//echo $checkCode;
//创建图片
$img=imagecreatetruecolor(110,30);
//背景默认是黑色
$bgcolor=imagecolorallocate($img,0,0,0);
imagefill($img,0,0,$bgcolor);
//创建新的颜色
$white=imagecolorallocate($img,255,255,255);
imagestring($img,rand(1,5),rand(2,90),rand(1,10),$checkCode,$white);
header("content-type:image/png");
imagepng($img);
?>