参考书籍:《细说PHP》、《PHP核心技术与最佳实践》
一、什么是会话控制
会话控制是一种面向连接的可靠通信方式。用于记录用户的登录信息,在网站中跟踪用户。
【为什么要使用会话控制?】
·HTTP协议是无状态协议
·会话控制可以在不同页面追踪一个用户
【会话跟踪的方式】
·使用超链接或者header()函数等重定向的方式,通过URL的GET请求附加参数的形式,将数据从一个页面传递到另一个页面;也可以通过隐藏表单将用户数据通过表单提交传送至另一个页面
·使用Cookie将用户信息存放在客户端,使其他程序能存取使用者的信息
·使用Session将用户信息存放在服务器端
二、Cookie的应用
1.向客户端计算机中设置cookie
PHP使用setCookie()函数来建立cookie:
Bool setCookie(String $name [,String $value [,String $expire [,String $path [,String $domain [,bool $secure [,bool $httponly]]]]]])
①name:cookie的识别名称
②value:cookie的值,如果值为FALSE会使客户端尝试删除这个cookie
③expire:cookie的生存期限,设置time()+xx秒,为空则表示浏览器关闭就消失
④path:cookie在服务器端的有效路径,当设置此值的时候,服务器只有在指定路径下的网页或程序可以存取此cookie,值是路径,默认为“/”
⑤domain:指定此cookie的作用域名,值是域名
⑥secure:规定cookie是否仅通过安全的HTTPS连接传送,当设置为true时,表示创建的 cookie只能在 HTTPS 连接中被浏览器传递到服务器端进行会话验证,如果是 HTTP 连接则不会传递该信息,默认FALSE
⑦httponly:规定是否只用HTTP访问cookie,通过程序(JS脚本、Applet等)将无法读取到Cookie信息,默认FALSE
2.在PHP脚本中读取cookie的资料内容
echo $_COOKIE["cookieName"]
3.删除cookie
①把有效时间设置为过去时间
setCookie("cookieName","cookieValue", time()-1);
②把一个cookie的值设置为空
setcookie("testcookie", "");
4. 使用Cookie的限制
·必须在HTML文件的内容输出之前设置;
·不同的浏览器对Cookie的处理不一致,且有时会出现错误的结果。
·限制是在客户端的。一个浏览器能创建的Cookie数量最多为30个,并且每个不能超过4KB,每个WEB站点能设置的Cookie总数不能超过20个。
5.cookie的存储机制
不同浏览器对每个域名下的cookie限制不同。Cookie也不是越多越好,会增加带宽,不要把cookie当成客户端存储器用。
Cookie保存在文件中(IE)或者浏览器内存中(Firefox),根据不同的浏览器决定存储方式。
6.PHP跨域和P3P协议
【为什么要跨域?】
正常情况下cookie只能在创造它的应用中获取,而想要建立统一应用平台,如在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统(单点登录)就要实现cookie的跨域。
【跨域的实现】
在设置cookie的时候$domain设置为要跨的域
【跨域会遇到的问题】
如果是跨域读取cookie,在读取的事情IE会屏蔽跨域cookie,所以要保证在对应设置cookie的时候设置了P3P
【P3P】
P3P是W3C公布的一项隐私保护推荐标准,以为用户提供隐私保护。
P3P标准的构想是:Web 站点的隐私策略应该告之访问者该站点所收集的信息类型、信息将提供给哪些人、信息将被保留多少时间及其使用信息的方式,如站点应做诸如 “本网站将监测您所访问的页面以提高站点的使用率”或“本网站将尽可能为您提供更合适的广告”等申明。访问支持P3P网站的用户有权查看站点隐私报告,然 后决定是否接受cookie 或是否使用该网站。
【利用P3P实现跨域】
header( 'P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"' );
三、session的应用
1.配置session
php.ini文件中
选项名 |
描述 |
默认值 |
session.auto_start |
是否自动启动session。在使用session功能时,在每个php脚本头部都会通过session_start()函数来启动session |
0(不启动) |
session.cookie_domain |
cookie有效作用域名 |
None |
session.cookie_lifetime |
传递sessionid的Cookie有效期(秒),0表示仅在浏览器打开期间有效 |
0 |
session.cookie_path |
传递会话id的cookie作用路径 |
/ |
session.name |
当做cookie name来使用的session标识名 |
PHPSWSSID |
session.save_path |
对于文件处理器,此值是创建会话数据文件的路径 |
/tmp |
session.use_cookies |
是否采用cookie在客户端保存会话ID(SID) |
1 |
session.use_trans_sid |
是否使用明码在URL中显示SID |
禁止 |
session.gc_probability |
定义每次初始化会话时,启动垃圾回收程序的概率,公式为:session.gc_probability/ session.gc_divisor |
1/100 |
session.gc_divisor |
||
session.gc_maxlifetime |
当session文件在规定值时间后还没有被访问的话,将会被视为“垃圾文件”,并且等待gc(垃圾回收)进程的调用的时候被清理掉 |
1440(24分钟) |
session.save_handler |
存储和检索与会话关联的数据的处理器名字,可以使用files、user、sqlite、memcache,自定义的处理器可用user |
files |
2.session的工作原理
Session启动:bool session_start(void);session在使用时必须先启动(要放在所有输出前)
Session id的创建:用户第一次访问网站时session_start()函数会创建唯一的session id,并通过HTTP响应头保存id至客户端的cookie中
用户再次访问时也会通过HTTP响应头将客户端cookie中保存的session id再携带过来,此时session_start()函数不会再分配新session id,而是去服务器寻找该session id对应的文件。
3.注册一个会话变量和读取session
①启动:bool session_start(void);
②注册:$_SESSION[“variableName”] = variableValue;
③读取:echo $_SESSION[“variableName”];
4.注销变量与销毁session
①结束会话,注销变量:bool session_destroy(void);用于关闭session的运作,清空会话资源,但不会释放当前session的相关变量,也不会删除保存在客户端cookie中的session id
②释放session中的单个变量:unset($_SESSION[“variableName”]);注意不要直接删除整个$_SESSION,否则就无法通过$_SESSION超全局数组注册变量了。
5.session入库
访问量大的站点,用默认的session存储方式并不合适,较优的方法是用数据库存取session。
<?php //session入库 //以为修改session机制必须借助session_set_save_handler()函数,该函数需要6个可以调用的回调函数,因此需要创建6个人对应的函数 //1.开启session机制 function sess_open() { //开启资源 //连接数据库 mysql_connect('localhost','root','root'); mysql_query('set names utf8'); mysql_query('use session'); echo __FUNCTION__,'<br/>'; }
//2.关闭session function sess_close() { //关闭资源 mysql_close(); echo __FUNCTION__,'<br/>'; }
//3.读取session function sess_read($sess_id) { //从数据库读取数据 //根据sess_id(由系统提供)获取数据 //读数据时要过滤掉过期的数据 $expire=time()-ini_get('session.gc_maxlifetime'); $sql="selsct * from session where sess_id='{$sess_id}' and sess_expire>='{$expire}'"; $res=mysql_query($sql); //得到的是一个数组 if($sess=@mysql_fetch_assoc($res)) { //得到一个序列化后的字符串 //要进行反序列化,read只负责读取数据,不负责加工数据 return $sess['sess_info']; } echo __FUNCTION__,'<br/>'; }
//4.写入session function sess_write($sess_id,$sess_info) { //向数据库中写入数据 $time=time(); $sql="replace into session values('{$sess_id}','{$sess_info}','{$time}')"; mysql_query($sql); echo __FUNCTION__,'<br/>'; }
//5.销毁session function sess_destroy($sess_id) { $sql="delete from session where sess_id='{$sess_id}'"; return mysql_query($sql); echo __FUNCTION__,'<br/>'; }
//6.回收session function sess_gc() { //从数据库删除过期的session数据 //判断session是否过期,过期的删除 $expire=ini_get('session.gc_maxlifetime'); //得到最迟的时间,在$expire之前的都是过期的 $expire=time()-$expire; $sql="delete from session where sess_expire < '{expire}'"; return mysql_query($sql); echo __FUNCTION__,'<br/>'; } //使用session_set_save_handler()修改session机制 session_set_save_handler('sess_open','sess_close','sess_read','sess_write','sess_destroy','sess_gc'); //想要使用session,必须要用session_start()来开启 session_start(); $_SESSION['name']='wangqixing'; $_SESSION['age']='23'; //session_destroy();
代码参考:http://www.cnblogs.com/wangjingwangjing/p/5286534.html