Cookie和Session
Cookie介绍
引入cookie的概念
思考:A页面中访问B页面的变量如何实现?
方法一:包含文件
方法二:get或者post传递
方法三:将数据保存到请求头中,目标页面就可以到请求头中获取数据。这就是cookie。
Cookie是放在请求头中的一个信息包。
cookie的原理
请求头和响应头
请求头的信息用来告知服务器客户端的信息
响应头的信息用来告知客户端服务器的信息
长连接
TCP:是一个连接协议
http:是一个访问协议
在http请求之前有一个TCP连接的过程,http响应后不立即关闭连接,而是等5秒,以便第二次访问的时候不需要建立连接,从而节省资源,提高效率。
Cookie使用
设置cookie
语法:setcookie(‘名’,’值’)
分析如下情况,为什么第一次访问报错?再次访问可以获取到cookie的值
刷新浏览器
原因:
第一次访问的时候请求头中没有cookie的信息,第一次访问服务器通过响应头将cookie的值发送到客户端
第二次再次访问的时候,cookie的信息就会自动存放到请求头中带到服务器去。服务器就可以获取cookie的值
Cookie保存在浏览器上
cookie的分类
cookie可以分为两类:临时性cookie和永久性cookie
临时性cookie:关闭浏览器cookie就消失
永久性cookie:关闭浏览器cookie不消失,在临时cookie基础上添加过期时间
语法:setcookie(名,值,过期时间),过期时间用时间戳
查看cookie
永久性cookie的作用,用来实现记住用户名和密码
脚下留心:cookie保存在浏览器上,火狐保存的cookie不可以通过ie等其他浏览器访问。那个浏览器保存的cookie那个浏览器访问。
Cookie中保存数据的类型
保存字符串
保存数字
不能保存布尔型
不能保存null型
不能保存数组和对象
总结:cookie只能保存字符串和数字。
删除cookie
Cookie名字支持下标
Cookie在浏览器上是没有数组概念的。浏览器请求到服务器,PHP将同名的参数转换成数组。
4-demo2.php上获取cookie
Cookie的有效目录
默认情况下,cookie只能在设置cookie页面当前目录及后代目录下起作用
我们要在整个站点目录下起作用,设置第四个参数。“/”表示根目录下有效。
Cookie支持子域名
多学一招:域名的基础知识
域名从级别上来分分为一级域名,二级域名,三级域名,…
www.baidu.com:一级域名
www.aa.baidu.com:二级域名
www.itcast.cn:一级域名
www.php.itcast.cn:二级域名
www.sh.itcast.cn:二级域名
域名从地区上分分为:国内域名,国际域名
国内域名:从域名上可以区分国家
国际域名:从域名上不能区分那个国家
.com: 表示公司 company
.co:表示公司,和.com是一样的,因为.com快耗尽了
.cc:表示中国公司
.net:表示与网络有关的公司
.gov:政府
www.aa.com 国际域名
www.aa.net 国际域名
www.aa.cn 国内域名(中国)
www.aa.tw 国内域名(台湾)
www.aa.jp 国内域名(日本)
www.aa.af 国内域名(阿富汗)
默认情况下,cookie的值是区分子域名的,我们可以通过设置域名使得cookie在所有的子域名中访问
运行结果
是否安全传输
setcookie(名字,值,过期时间,有效目录,子域名,是否安全传输=false)
默认是false。
如果是true只能是https协议才能传输cookie,http不能传输。
是否安全访问
setcookie(名字,值,过期时间,有效目录,子域名,是否安全传输,是否安全访问=false)
默认情况下,js和php都可以获取cookie的值
设为true,表示安全访问,只能通过PHP获取cookie,不能通过js获取。
Cookie的缺点
- cookie保存在客户端安全性比较低
- cookie只能保存数字和字符串,可控性比较差
- 增加请求时数据负载
- 浏览器对cookie是有大小限制的,一般的4K。
Session(会话)
- session是基于cookie技术的
- session是将信息保存在服务器的技术,
- 要使用会话,需要开启会话。session_start(),默认情况下会话不会自动开启。
- 要自动开启会话,在php.ini文件中设置session.auto_start = 1,重启服务器。
- session_id():获取会话编号
- session_name():获取会话名称
- session可以保存除了资源以外的任何数据类型。
- 重复开启会话会报错
可以通过@屏蔽错误
session的执行过程
第一步:当使用session_start()函数,PHP就从打开session仓库。
如果是第一次访问,服务器会给客户端赋一个唯一的会话id。这个id保存在cookie中,在后面的访问中通过会话id访问会话的内容。
如果不是第一次访问,通过会话id加载对应的会话文件。
第二步:在PHP运行过程中,PHP可以对会话进行操作
第三步:当PHP脚本执行结束,没有被销毁的会话自动的保存到session仓库中,以便下次访问的时候加载使用。
只能访问自己的会话,不能访问别人的会话,因为每个人的会话编号不同。
会话的配置
- session.save_path=”F:\wamp\tmp\tmp”:会话加载的位置
- session.auto_start = 0:是否自动开启会话
- session.name = PHPSESSID:设置会话编号的名字
- session.cookie_path = /:保存会话编号的cookie整站有效
- session.cookie_domain =:保存会话编号的cookie当前域名下有效
- session.gc_maxlifetime = 1440:会话过期时间,默认1440秒=24分钟
- session.cookie_lifetime = 0:会话编号在客户端保存的时间,0表示关闭浏览器就失效
- session.save_handler = files:会话通过文件来保存
销毁会话
session_destroy()
调用此函数会删除存储介质中的文件。
执行了销毁会话就不执行会话写操作
垃圾回收
测试
PHP认为超出了会话过期时间的文件是垃圾文件。PHP垃圾回收机制自动执行垃圾回收。
session和cookie的区别
相同点
- 他们都是会话技术,都是有生命周期的
- 都是无状态性的
不同点
cookie |
session |
|
保存的位置 |
客户端 |
服务器端 |
数据大小 |
4K |
没有限制 |
数据类型 |
字符串和数字 |
除了资源以为的所有类型 |
安全性 |
低 |
高 |
Cookie和session都是实现在整个访问过程中可以访问到变量的值。
禁用cookie对session的影响
脚下留心:默认情况下,session是基于cookie技术的,如果禁用了cookie,session也是无法使用
服务器是无法控制客户端是否禁用cookie,解决方法:通过get传递会话编号。
实现方法;
在php.ini中设置session.use_only_cookies = 0:表示session不仅仅依赖于cookie
在php.ini中设置session.use_trans_sid = 1:表示运行通过其他方式传输sessionid。
页面中get提交的地址后面都会自动添加sessionid参数,表单中都会添加sessionid的隐藏域
Session入库
在处理大量数据的时候,会话保存到数据库中文件中效率要高。
创建数据库
create table `session`(
sess_id varchar(50) primary key comment ‘会话id’,
sess_value varchar(2000) comment ‘会话的值’,
sess_expires int comment ‘会话产生时间’
)engine=memory charset=utf8 comment ‘会话表’
思考:
- 时间为什么不用datetime而用int?
答:datetime占用8个字节,int占用4个字节
- 表引擎为啥用memory
答:memory数据保存在内存中,执行效率很高,但memory引擎只要重启MySQL服务器,数据全部清空。
Session入库
通过session_set_save_handler()函数设置会话的保存方式
on duplicate key update:当插入记录与主键或唯一键冲突的时候就执行update操作。
例题
<?php
header(‘content-type:text/html;charset=utf-8’);
//开启会话时候执行
function open() {
//连接数据库
mysql_connect(‘localhost’,’root’,’root’);
mysql_select_db(‘data’);
mysql_query(‘set names utf8’);
}
//关闭会话的时候执行
function close() {
}
/**
*读取会话的时候执行
*@param $sess_id string 会话id
*/
function read($sess_id) {
$sql=”select sess_value from session where sess_id=’$sess_id'”;
$rs=mysql_query($sql);
if($rows=mysql_fetch_row($rs))
return $rows[0];
return ”;
}
/**
*写入会话的时候执行
*@param $sess_id string 会话编号
*@param $sess_value string 会话的值
*/
function write($sess_id,$sess_value) {
$time=time(); //会话产生的时间
$sql=”insert into session values (‘$sess_id’,’$sess_value’,$time) on duplicate key update sess_value=’$sess_value'”;
return mysql_query($sql);
}
/**
*销毁会话的时候执行,调用session_destroy()执行
*@param $sess_id string 会话id
*/
function destroy($sess_id) {
$sql=”delete from session where sess_id=’$sess_id'”;
return mysql_query($sql);
}
/**
*垃圾回收的时候执行
*@param $lifetime int 会话过期时间
*/
function gc($lifetime) {
$expires=time()-$lifetime; //垃圾文件的临界值
$sql=”delete from session where sess_expires<$expires”;
return mysql_query($sql);
}
ini_set(‘session.gc_probability’,1000); //执行垃圾回收的概率是1000/1000
ini_set(‘session.gc_maxlifetime’,2);
session_set_save_handler(‘open’,’close’,’read’,’write’,’destroy’,’gc’); session_start(); //开启会话
$_SESSION[‘name’]=’tom’;
unset($_SESSION[‘sex’]);
unset($_SESSION[‘add’]);
$_SESSION[‘aa’]=10;
session_destroy();
脚下留心:session_set_save_handler()一定要写在session_start()前面