php中cookie和session的区别

jackxiang 2008-5-27 16:13 | |
http协议是一种无状态的连接,要想跟踪用户的行为就必须有一个能工作于不同于页面的变量,在PHP中可以用cookie和session两种办法实现。
cookie大家比较熟悉了,就是在把变量存为客户端上的一个文件而已,但是如果客户禁止cookie就没办法了。这就需要session了,在PHP4 中,session可以有两种办法实现,一是用cookie,即把sessionID保存在cookie文件中;二是把sessionID附带在URL上进行传递。
虽有这两种办法实现,但至于使用哪种方法是不用程序员操心的,PHP会自动检查客户cookie的设置的(指linux/unix平台,Win32未知),并且默认的是优先使用cookie(你可以修改php.ini文件中的[session]一节的session.use_cookies的值来改变)。当然你也可以强制使用URL来传递SessionID,如下:
<a href="submit.php<?=sessionID;?>">提交表单</a>
仅在链接中加一句<?=sessionID;?>就行了,简单吧?在php.ini中还有许多关于Session的设置,如 session.cookie_lifetime是session的有效时间等,都在[session]一节中,若看看的话会对PHP中的session 有更多的理解的。
   具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。同时我们也看到,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到保存标识的目的,但实际上它还有其他选择。

     cookie机制。正统的cookie分发是通过扩展HTTP协议来实现的,服务器通过在HTTP的响应头中加上一行特殊的指示以提示浏览器按照指示生成相应的cookie。然而纯粹的客户端脚本如JavaScript或者VBScript也可以生成cookie。而cookie的使用是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器检查所有存储的cookie,如果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置,则把该 cookie附在请求资源的HTTP请求头上发送给服务器。
     cookie的内容主要包括:名字,值,过期时间,路径和域。路径与域一起构成cookie的作用范围。若不设置过期时间,则表示这个cookie的生命期为浏览器会话期间,关闭浏览器窗口,cookie就消失。这种生命期为浏览器会话期的cookie被称为会话cookie。会话cookie一般不存储在硬盘上而是保存在内存里,当然这种行为并不是规范规定的。若设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些 cookie仍然有效直到超过设定的过期时间。存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存里的 cookie,不同的浏览器有不同的处理方式
     session机制。session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。
  
     当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个session标识(称为session id),如果已包含则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。
     保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发挥给服务器。一般这个cookie的名字都是类似于 SEEESIONID。但cookie可以被人为的禁止,则必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。
     经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面。还有一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。比如:
      <form name="testform" action="/xxx">
      <input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
      <input type="text">
      </form>
实际上这种技术可以简单的用对action应用URL重写来代替。

在一个页面设置一个cookie时,必须刷新或到下一个页面才可以用 $_COOKIE 得到变量的值.

原因是因为当页面第一次被浏览器访问载入时,页面中的 cookie 会被设置,将其发送存储到客户端指定的

存储位置,所以$_COOKIE没有接收到客户端发送过来的 cookie 变量的值,当刷新或到下一个页面时,客户

端会在页面程序在服务器端运行之前,发送与该地址相对应的 cookie到服务器端,所以 $_COOKIE 可以得

到的值!
说白了就是当每一个页面被访问时,如果客户端找到了与访问地址相对应的 cookie 时,会在程序在服务器

端运行之前发送这个 cookie 到服务器端. (个人对此的看法)

本人表达能力不强,如有不明,还请抱歉!

php中设置cookie数组的时候,不可以用像php中的那个添加数据的方法:
<?php
setcookie('my_cookie[]', 1);
setcookie('my_cookie[]', 2);
print_r($_COOKIE);    // Array ( [my_cookie] => Array ( [0] => 1 ))
                      // 数组的值添加是添加成功了,不过索引没有变,后面的数据将前的数据覆盖了!

由此得到
       my_cookie[],默认指向数据的第一元素的位置,即索引为

0 的位置. 注意与php中的不一样! 以后用cookie数据记住要指定数组元素索引哦!
      
$my_cookie[] = 1;
$my_cookie[] = 2;
print_r($my_cookie); //Array ( [0] => 1 [1] => 2)
?>

删除 cookie 变量的两个方法:
1.php
<?php
setcookie('user_name_1', 'zhaofei299', time()+3600); // 生存期为 1 个小时
setcookie('user_name_2', 'ZHAOFEI299', time()+3600); // 生存期为 1 个小时
?>

2.php
<?php
setcookie('user_name_1');                // 第一种              
setcookie('user_name_2', "", time()-1); // 第二种
print_r($_COOKIE);                       // 刷新页面2下以上会输出 Array ( [user_name_1] => )

/*为什么超级全局变量 $_COOKIE 中的 user_name_1 没有被删除(变量为空并不代表不存在),而

user_name_2被删除了? 那是因为两个删除变量的方式不同!

第一种: 是设置了 cookie 的生存期, 只不过是将它的值默认设置为空,生存期为与浏览器一样,浏览器

关闭时,cookie才会删除!所以当重新打开一个浏览器,输出地址时,才会发现 cookie 变量全部被删除了!

将2.php 中两个 setcookie() 函数部分注释掉看看(重新输出了地址)!

第二种: 也是设置了 cookie 的生存期,是使 cookie 的生存期一定过期, cookie 也就被删除,所以刷

新页面,客户端向服务器端发送 cookie 时, $_COOKIE 并没有能够得到该cookie变量的值!
*/
?>

会话id默认储放在客户端Cookie中!
<?php
session_start();
print_r($_COOKIE);
?>
cookie的设置有两种方法

header('set-cookie:user=zhaofei299');
setcookie('user', 'zhaofei299');

会话变量不能被GET数据或POST数据重载!

使用session变量传递数组,对象时无需序列化!
使用session变量传递对象时,在调用session_start()之前,必须包含该对类对象的定义,反序列化

(serialize)也是如此!


删除单个会话变量可以使用unset($_SESSION['***']) 直接删除!

删除所有的会话变量不可以用unset($_SESSION),因为这样会将所有的会话信息删除,包含存储在COOKIE

中的PHPSESSID,也就是破坏了两个页面之间的会话联系,应该使用$_SESSION = array();

消除会话id,使页面之间失去联系!
session_destroy();


程序清单1.1
<?php
session_start();
header('content-type:text/html;charset=utf-8');
$_SESSION['a'] = 'a';
$_SESSION['b'] = 'b';

unset($_SESSION);        //测试后,再注释下看看
$_SESSION['user'] = 'zhaofei299';
echo 'SESSION_ID: '.session_id().'<br />';
echo '<a href="3.php" target="_blank">测试下</a>';
?>


<?php
session_start();

echo $_SESSION['user'];
echo session_id();         //会话变量改变了
?>

会话id(session_id)的两种方式传递:
1.cookie
2.url

因为默认session是基于cookie的,而cookie又是跟随http协议发送的,所以与cookie一样,在

session_start()之前不能有任何输出!

现在主要说一说第二种,通过 url 传递会话id
php中已经定义SID这个常量来得到 会话的id


sesssin_id 的使用!
<?php
session_start();
echo defined('SID')?'true':'false'; // true
echo SID; //什么也没有?
?>
为什么SID的值会是null 呢?是它哪里有问题了?
原因是因为 session 默认是基于 cookie 的,而 SID 只有 session_id 通过 url
传递数据时才会被赋值!
在浏览器中将 cookie 禁用,你就会发现 SID 有了输出,而不是 null!


删除session

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

大家都知道session变量是保存在服务器端的,也就是说session的变量会保存在服务器中一个目录中,我

们可以在php.ini中的session.save_path 那里可以找到session文件中保存的地址.

默认的session的生存期是浏览的关闭就结束,但要知道会话过期结束后,当打开页面session_start()会

判断会话id 是否存在,如果不存在就创建一个,否则将该会话id 的变量载入页面!因为过期session_id会

被创建一个新的,但它保存在服务器端的session文件并没有被删除(关闭浏览器,打开session文件保存

地看看),所以要用session_destory()函数清除会话id,并同时清除相应的会话文件,这样的话才能做到最

彻底的清除!


session_id 使用 url 传递session 变量数据时,因为session_start()开启会话时会判断会话id 是否存

在,如果不存在就创建一个,否则将该会话id 的变量载入页面!
而现在是使用url 来传递session_id,然而每一次 刷新/进入页面 都会生成一个会话id,所以页面之间就

不能得到在另一页面设置过的session_id 的变量,那么使用 session也就没什么意义了!

解决方法:在session_start()之前,手动设置页面的session_id,这样页面的就可以得到前一页中所设置的

session变量的,也就实现了会话的传递,如下代码可以说明!


//已禁用 cookie

1.php
<?php
session_start();
$_SESSION['user'] = 'zhaofei299';
echo '<a href="2.php?'.SID.'">下一页</a>';
?>

1.php的第4行代码也可以写成:echo '<a href="2.php">下一页</a>';

可以设置php.ini 中的 session.use_trans_sid 为1,这样当使用 url 传递会话 id 时,
浏览器会自动将 session_id 追加到 url 的后面!
就好像 在浏览器中 输入: www.baidu.com 一样,浏览器会自动将其更换成 http://www.baidu.com/

2.php
<?php
session_id($_GET['PHPSESSID']);   // 手动设置session_id,这种就可以使用前一个页面的

session_id 的变量了,也就实现了会话!
session_start();
print_r($_SESSION);
?>

常用session函数:

bool   session_start(void); 初始化session
bool   session_destroy(void): 删除服务器端session关联文件。
string session_id() 当前session的id
string session_name() 当前存取的session名称,也就是客户端保存session ID的cookie名称.默认

PHPSESSID。
array session_get_cookie_params() 与这个session相关联的session的细节.
string session_cache_limiter() 控制使用session的页面的客户端缓存
ini    session_cache_expire() 控制客户端缓存时间
bool   session_destroy()     删除服务器端保存session信息的文件
void   session_set_cookie_params ( int lifetime [, string path [, string domain [, bool

secure [, bool httponly]]]] )设置与这个session相关联的session的细节
bool session_set_save_handler ( callback open, callback close, callback read, callback

write, callback destroy, callback gc )定义处理session的函数,(不是使用默认的方式)
bool session_regenerate_id([bool delete_old_session]) 分配新的session id    

作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/1048/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!


最后编辑: jackxiang 编辑于2008-5-27 16:17
评论列表
发表评论

昵称

网址

电邮

打开HTML 打开UBB 打开表情 隐藏 记住我 [登入] [注册]