php session和cookie使用说明


Posted in PHP onApril 07, 2010

1. PHP的COOKIE

cookie 是一种在远程浏览器端储存数据并以此来跟踪和识别用户的机制。PHP在http协议的头信息里发送cookie, 因此setcookie() 函数必须在其它信息被输出到浏览器前调用,这和对header() 函数的限制类似。1.1 设置cookie:
可以用setcookie() 或setrawcookie() 函数来设置cookie。也可以通过向客户端直接发送http头来设置.
1.1.1 使用setcookie()函数设置cookie:
bool setcookie( stringname [, stringvalue [, int expire [, stringpath [, stringdomain [, bool secure [, bool httponly]]]]]] )
name: cookie变量名value: cookie变量的值expire: 有效期结束的时间,
path: 有效目录,
domain: 有效域名,顶级域唯一secure: 如果值为1,则cookie只能在https连接上有效,如果为默认值0,则http和https都可以.
例子:

<?php 
$value= 'something from somewhere'; 
setcookie("TestCookie", $value); 
/* 简单cookie设置*/setcookie("TestCookie", $value, time()+3600); /* 有效期1个小时*/setcookie("TestCookie", $value, time()+3600, "/~rasmus/", ".example.com", 1); /* 有效目录/~rasmus,有效域名example.com及其所有子域名*/ 
?>

设置多个cookie变量: setcookie('var[a]','value');用数组来表示变量,但他的下标不用引号.这样就可以用$_COOKIE[‘var'][‘a']来读取该COOKIE变量.

1.1.2. 使用header()设置cookie;
header("Set-Cookie: name=$value[;path=$path[;domain=xxx.com[; ]]");
后面的参数和上面列出setcookie函数的参数一样.
比如:

$value= 'something from somewhere'; 
header("Set-Cookie:name=$value");

1.2 Cookie的读取:

直接用php内置超级全局变量$_COOKIE就可以读取浏览器端的cookie.
上面例子中设置了cookie"TestCookie",现在我们来读取:

print$_COOKIE['TestCookie'];

COOKIE是不是被输出了?!

1.3 删除cookie
只需把有效时间设为小于当前时间, 和把值设置为空.例如:
setcookie("name","",time()-1);
用header()类似.

1.4 常见问题解决:

1) 用setcookie()时有错误提示,可能是因为调用setcookie()前面有输出或空格.也可能你的文档使从其他字符集转换过来,文档后面可能带有BOM签名(就是在文件内容添加一些隐藏的BOM字符).解决的办法就是使你的文档不出现这种情况.还有通过使用ob_start()函数有也能处理一点.
2) $_COOKIE受magic_quotes_gpc影响,可能自动转义3) 使用的时候,有必要测试用户是否支持cookie
<!--[if!supportLineBreakNewLine]-->

1.5 cookie工作机理:

有些学习者比较冲动,没心思把原理研究,所以我把它放后面.
a) 服务器通过随着响应发送一个http的Set-Cookie头,在客户机中设置一个cookie(多个cookie要多个头).
b) 客户端自动向服务器端发送一个http的cookie头,服务器接收读取.

HTTP/1.x 200 OK
X-Powered-By: PHP/5.2.1
Set-Cookie: TestCookie=something from somewhere; path=/
Expires: Thu, 19 Nov 2007 18:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-type: text/html

这一行实现了cookie功能,收到这行后Set-Cookie: TestCookie=something from somewhere; path=/
浏览器将在客户端的磁盘上创建一个cookie文件,并在里面写入:

TestCookie=something from somewhere;
这一行就是我们用setcookie('TestCookie','something from somewhere','/');的结果.也就是用header('Set-Cookie: TestCookie=something from somewhere; path=/');的结果.
<!--[endif]-->

2. PHP的Session

session使用过期时间设为0的cookie,并且将一个称为session ID的唯一标识符(一长串字符串),在服务器端同步生成一些session文件(可以自己定义session的保存类型),与用户机关联起来.web应用程序存贮与这些session相关的数据,并且让数据随着用户在页面之间传递.

访问网站的来客会被分配一个唯一的标识符,即所谓的会话ID。它要么存放在客户端的cookie,要么经由URL 传递。会话支持允许用户注册任意数目的变量并保留给各个请求使用。当来客访问网站时,PHP 会自动(如果session.auto_start 被设为1)或在用户请求时(由session_start() 明确调用或session_register() 暗中调用)检查请求中是否发送了特定的会话ID。如果是,则之前保存的环境就被重建。2.1 sessionID的传送2.1.1 通过cookie传送sessin ID

使用session_start()调用session,服务器端在生成session文件的同时,生成session ID哈希值和默认值为PHPSESSID的session name,并向客户端发送变量为(默认的是)PHPSESSID(session name),值为一个128位的哈希值.服务器端将通过该cookie与客户端进行交互.
session变量的值经php内部系列化后保存在服务器机器上的文本文件中,和客户端的变量名默认情况下为PHPSESSID的coolie进行对应交互.
即服务器自动发送了http头:header('Set-Cookie: session_name()=session_id(); path=/');
即setcookie(session_name(),session_id());
当从该页跳转到的新页面并调用session_start()后,PHP将检查与给定ID相关联的服务器端存贮的session数据,如果没找到,则新建一个数据集.

2.1.2 通过URL传送session ID
只有在用户禁止使用cookie的时候才用这种方法,因为浏览器cookie已经通用,为安全起见,可不用该方法.
<a href="p.php?<?php print session_name() ?>=<?php print session_id() ?>">xxx</a>,也可以通过POST来传递session值.

2.2 session基本用法实例

<?php 
// page1.php 
session_start(); 
echo'Welcome to page #1'; 
/* 创建session变量并给session变量赋值*/$_SESSION['favcolor'] = 'green'; 
$_SESSION['animal'] = 'cat'; 
$_SESSION['time'] = time(); // 如果客户端使用cookie,可直接传递session到page2.php 
echo'<br /><a href="page2.php">page 2</a>'; 
// 如果客户端禁用cookie 
echo'<br /><a href="page2.php?' . SID . '">page 2</a>'; 
/* 
默认php5.2.1下,SID只有在cookie被写入的同时才会有值,如果该session 
对应的cookie已经存在,那么SID将为(未定义)空*/ 
?> 
<?php 
// page2.php 
session_start(); 
print$_SESSION['animal']; // 打印出单个session 
var_dump($_SESSION); // 打印出page1.php传过来的session值 
?>

2.3 使用session函数控制页面缓存.
很多情况下,我们要确定我们的网页是否在客户端缓存,或要设置缓存的有效时间,比如我们的网页上有些敏感内容并且要登录才能查看,如果缓存到本地了,可以直接打开本地的缓存就可以不登录而浏览到网页了.

使用session_cache_limiter('private');可以控制页面客户端缓存,必须在session_start()之前调用.
更多参数见http://blog.chinaunix.net/u/27731/showart.php?id=258087的客户端缓存控制.
控制客户端缓存时间用session_cache_expire(int);单位(s).也要在session_start()前调用.

这只是使用session的情况下控制缓存的方法,我们还可以在header()中控制控制页面的缓存.

2.4 删除session

要三步实现.
<?php
session_destroy(); // 第一步: 删除服务器端session文件,这使用setcookie(session_name(),'',time()-3600); // 第二步: 删除实际的session:
$_SESSION= array(); // 第三步: 删除$_SESSION全局变量数组?>

2.5 session在PHP大型web应用中的使用对于访问量大的站点,用默认的session存贮方式并不适合,目前最优的方法是用数据库存取session.这时,函数bool session_set_save_handler( callbackopen, callbackclose, callbackread, callbackwrite, callbackdestroy, callbackgc )就是提供给我们解决这个问题的方案.
该函数使用的6个函数如下:

1. bool open() 用来打开会话存储机制,

2. bool close() 关闭会话存储操作.

3. mixde read() 从存储中装在session数据时使用这个函数4. bool write() 将给定session ID的所有数据写到存储中5. bool destroy() 破坏与指定的会话ID相关联的数据6. bool gc() 对存储系统中的数据进行垃圾收集例子见php手册session_set_save_handler() 函数.
如果用类来处理,用session_set_save_handler(
array('className','open'),
array('className','close'),
array('className','read'),
array('className','write'),
array('className','destroy'),
array('className','gc'),
)
调用className类中的6个静态方法.className可以换对象就不用调用静态方法,但是用静态成员不用生成对象,性能更好.

2.6 常用session函数:

bool session_start(void); 初始化session
bool session_destroy(void): 删除服务器端session关联文件。stringsession_id() 当前session的id
stringsession_name() 当前存取的session名称,也就是客户端保存session ID的cookie名称.默认PHPSESSID。arraysession_get_cookie_params() 与这个session相关联的session的细节.
stringsession_cache_limiter() 控制使用session的页面的客户端缓存ini session_cache_expire() 控制客户端缓存时间bool session_destroy() 删除服务器端保存session信息的文件void session_set_cookie_params( int lifetime [, stringpath [, stringdomain [, bool secure [, bool httponly]]]] )设置与这个session相关联的session的细节bool session_set_save_handler( callbackopen, callbackclose, callbackread, callbackwrite, callbackdestroy, callbackgc )定义处理session的函数,(不是使用默认的方式)
bool session_regenerate_id([bool delete_old_session]) 分配新的session id

2.7 session安全问题攻击者通过投入很大的精力尝试获得现有用户的有效会话ID,有了会话id,他们就有可能能够在系统中拥有与此用户相同的能力.
因此,我们主要解决的思路是效验session ID的有效性.
<?php

if(!isset($_SESSION['user_agent'])){
$_SESSION['user_agent'] = $_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT'];
}

/* 如果用户session ID是伪造*/elseif($_SESSION['user_agent'] != $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']) {
session_regenerate_id();
}
?>

2.8 Session通过cookie传递和通过SID传递的不同:
在php5.2.1的session的默认配置的情况下,当生成session的同时,服务器端将在发送header set-cookie同时生成预定义超级全局变量SID(也就是说,写入cookie和抛出SID是等价的.),当$_COOKIE['PHPSESSID']存在以后,将不再写入cookie,也不再生成超级全局变量SID,此时,SID将是空的.

2.9 session使用实例<?php
/**
* 效验session的合法性*
*/functionsessionVerify() {
if(!isset($_SESSION['user_agent'])){
$_SESSION['user_agent'] = MD5($_SERVER['REMOTE_ADDR']
.$_SERVER['HTTP_USER_AGENT']);
}
/* 如果用户session ID是伪造,则重新分配session ID */elseif($_SESSION['user_agent'] != MD5($_SERVER['REMOTE_ADDR']
. $_SERVER['HTTP_USER_AGENT'])) {
session_regenerate_id();
}
}

/**
* 销毁session
* 三步完美实现,不可漏*
*/functionsessionDestroy() {
session_destroy();
setcookie(session_name(),'',time()-3600);
$_SESSION= array();
}
?>

注明:

session 出现头信息已经发出的原因与cookie一样.
在php5中,所有php session 的注册表配置选项都是编程时可配置的,一般情况下,我们是不用修改其配置的.要了解php的session注册表配置选项,请参考手册的Session 会话处理函数处.
session的保存数据的时候,是通过系列化$_SESSION数组来存贮,所以有系列化所拥有的问题,可能有特殊字符的值要用base64_encode函数编码,读取的时候再用base64_decode解码

PHP 相关文章推荐
随机广告显示(PHP函数)
Oct 09 PHP
基于mysql的bbs设计(四)
Oct 09 PHP
PHP安全配置
Dec 06 PHP
获取用户Ip地址通用方法与常见安全隐患(HTTP_X_FORWARDED_FOR)
Jun 01 PHP
ThinkPHP空模块和空操作详解
Jun 30 PHP
VB中的RasEnumConnections函数返回632错误解决方法
Jul 29 PHP
php使用gzip压缩传输js和css文件的方法
Jul 29 PHP
php删除txt文件指定行及按行读取txt文档数据的方法
Jan 30 PHP
PHP实现电商订单自动确认收货redis队列
May 17 PHP
PHP创建单例后台进程的方法示例
May 23 PHP
由php中字符offset特征造成的绕过漏洞详解
Jul 07 PHP
PHP数组内存利用率低和弱类型详细解读
Aug 10 PHP
DedeCMS dede_channeltype表字段注释
Apr 07 #PHP
php抓取https的内容的代码
Apr 06 #PHP
php中几种常见安全设置详解
Apr 06 #PHP
PHP 检查扩展库或函数是否可用的代码
Apr 06 #PHP
php下关于中英数字混排的字符串分割问题
Apr 06 #PHP
Blitz templates 最快的PHP模板引擎
Apr 06 #PHP
PHP数组内存耗用太多问题的解决方法
Apr 05 #PHP
You might like
Discuz 5.0 中读取纯真IP数据库函数分析
2007/03/16 PHP
ThinkPHP的URL重写问题
2014/06/22 PHP
PHP原生函数一定好吗?
2014/12/08 PHP
微信公众平台之快递查询功能用法实例
2015/04/14 PHP
php 参数过滤、数据过滤详解
2015/10/26 PHP
JS 用6N±1法求素数 实例教程
2009/10/20 Javascript
javascript实现浏览器窗口传递参数的方法
2014/09/03 Javascript
浅谈js 闭包引起的内存泄露问题
2015/06/22 Javascript
javascript作用域问题实例分析
2015/07/13 Javascript
jQuery实现可用于博客的动态滑动菜单完整实例
2015/09/17 Javascript
JS实现漂亮的淡蓝色滑动门效果代码
2015/09/23 Javascript
实例详解jQuery表单验证插件validate
2016/01/18 Javascript
AngularJS入门教程之链接与图片模板详解
2016/08/19 Javascript
JS实现图片局部放大或缩小的方法
2016/08/20 Javascript
javascript中this用法实例详解
2017/04/06 Javascript
详解Node.js实现301、302重定向服务
2017/04/07 Javascript
js 计算图片内点个数的示例代码
2019/04/04 Javascript
跟老齐学Python之模块的加载
2014/10/24 Python
Python制作简易注册登录系统
2016/12/15 Python
python去除字符串中的换行符
2017/10/11 Python
python pandas修改列属性的方法详解
2018/06/09 Python
Python中Proxypool库的安装与配置
2018/10/19 Python
python中栈的原理及实现方法示例
2019/11/27 Python
利用Tensorflow构建和训练自己的CNN来做简单的验证码识别方式
2020/01/20 Python
浅谈Python中的继承
2020/06/19 Python
基于Python 的语音重采样函数解析
2020/07/06 Python
详解Scrapy Redis入门实战
2020/11/18 Python
汽车销售顾问求职自荐信
2014/01/01 职场文书
女方回门宴答谢词
2014/01/14 职场文书
仓管员岗位责任制
2014/02/19 职场文书
培训主管的职业生涯规划
2014/03/06 职场文书
党员干部四风问题整改措施思想汇报
2014/10/12 职场文书
2014年施工员工作总结
2014/11/18 职场文书
浅谈vue2的$refs在vue3组合式API中的替代方法
2021/04/18 Vue.js
对Golang中的FORM相关字段理解
2021/05/02 Golang
解决MySQL报“too many connections“错误
2022/04/19 MySQL