聊聊Cookie和Session的那些事

本文为天凌(tianling)原创,欢迎分享,但请注明出处!

咱做web开发的,任何时候都少不了要和Cookie以及Session打交道,我们平时主要用他们来实现用户的登陆和用户的信息存储。说到Cookie和Session,我们一般会很简单地想到他们一个是客户端的存储机制,一个是服务器端的存储机制。然而,事实是否真的仅仅是这样的呢?

在聊之前,我们先一起思考如下几个问题:

1.我们一般认为Cookie运行在客户端而Session运行在服务器端,所以当我们关闭浏览器(即将客户端和服务器端的链接断开)时,Session一般就消失了而Cookie可以保留。这是真的吗?

2.浏览器禁止Cookie,Cookie就不能用了,但Session不会受到影响,这是真的吗?

3.Session是否真的比Cookie更加安全呢?

4.我们发现,使用IE登陆腾讯网后,在同一台机子上使用Firefox打开腾讯的页面,发现已经有了登陆的状态,那么是否说明Cookie可以在不同浏览器之间共享呢?

5.如果把别人的Cookie复制到我的电脑上,假设我使用一样的浏览器,那么我是否可以直接登陆别人的账号呢?

其实tianling我在学习web开发并且实践的过程中,一直有这样一个疑惑:我们用Cookie和Session进行用户的登陆和信息管理,可是Cookie和Session究竟是如何工作的呢?为什么我们关闭浏览器后Session就注销了,而Cookie却可以一直保留?

好,那么什么是cookie?

cookie是存储在客户端的一小段数据,客户端通过HTTP协议和服务器端进行Cookie交互。也就是说,Cookie独立于任何语言存在,无论PHP,JSP,ASP下的Cookie,都是一样的,因为他们都能被JavaScript这种客户端脚本读取到。PHP之类的语言通过发送HTTP指令,通过浏览器等客户端实现对Cookie的操作,其本身是无法设置或操作Cookie的。

Cookie主要是参照RFC2109标准由客户端实现生成,使用等整个过程,服务器端则参照此标准实现和客户端之间的交互指令。

我们都知道PHP设置Cookie的函数setcookie()。

我们来看看其在C解释器中的函数原型:

Bool setcookie(string $name[,string $value[,int $expire = 0[,string $path[,string $domain[,bool secure = false[,bool $httponly = false]]]]]])

对web开发有了解的朋友应该是很熟悉前面几个参数的,即cookie对应的键,值,有效时间,有效目录,作用域名。

对于第六个参数$secure,它主要是用来设置是否对cookie进行加密传输,默认为false,若设置为ture,则只有在使用HTTPS的情况下,这个cookie才可以被设置。

第七个参数$httponly,设置是否只使用HTTP访问cookie,若设置为ture,则客户端脚本(如JavaScript)将无法访问该cookie,这个参数一定程度上可以降低XSS攻击的风险,但注意不是所有浏览器都支持该参数,而且只在PHP5.2.0以上版本有效。

好,现在让我们看一段PHP代码:

<?php
	$cookie_1 = setcookie("cookie1","tianling",time()+3600,'','','',1);
	$cookie_2 = setcookie("cookie2","Manchester United");
	if($cookie_1 && $cookie_2)
		print_r($_COOKIE);
?>

直接在浏览器运行这个脚本,我们发现显示了一个空数组array()

而刷新一下页面,显示如下图:



这说明PHP在当前页设置的cookie不是立即生效的,需要等到下一个页面才能生效。这是由于设置在这个页面里的cookie命令由服务器传递给客户端浏览器,需要到下一个页面,即下一次连接,浏览器才能把cookie从机器里取出传递回服务器。但注意JavaScript这类客户端脚本设置的Cookie是立即生效的。

然后,我们在控制台通过JavaScript获取cookie,如下图:


我们可以清楚地看到js只能获取到cookie2,这是因为cookie1把httponly设置成了ture,从而屏蔽了js脚本对cookie的读取。

我们下面来聊聊cookie的存储机制。

前面说到,cookie是保存在客户端的一小段数据,那么它究竟保存在哪呢?

有两种情况,一种是保存在文件中,一种是保存在浏览器内存中。

对于第一种情况,不同浏览器有不同的管理机制,比如IE保存在每个域名下的文本文件,而Firefox和Chrome在SQLite数据库中进行管理。我们现在分别就第一,第二种情况进行一些讨论。

我们打开Chrome的cookie管理工具,如下图


可以看到所有Chrome存储在本地(内存)的cookie,我们搜索本地服务器127.0.0.1



可以看到我们刚刚生成的两条Cookie,好,我们现在重启浏览器。

再次查询


我们发现cookie1还在而cookie2不见了,这是因为我们在设置cookie参数时把失效时间设置为空,也就是当浏览器关闭时失效,这时cookie存储在内存中,当Chrome进程终止,其系统资源被回收,这时存储于内存中的cookie自然也就被注销了。很容易理解,我们如果重新运行PHP脚本则Cookie1和Cookie2都会重新生成。

现在我们打开Safari的cookie管理器,查找127.0.0.1


我们发现只有缓存文件而没有cookie。现在理解了吧,cookie是由浏览器等客户端完全独立管理的。因为不同浏览器的Cookie管理机制不同,所以cookie不可能在浏览器之间共享。对于第四个问题,其实是因为我们在安装腾讯QQ时自动安装了针对不同浏览器的插件,可以识别已经登陆的QQ号码而自动登陆。朋友们可以试试把QQ完全卸载再从网页登陆腾讯网,哈哈,所以这和Cookie共享是完全没有任何关系的。

刚刚聊到存在内存中的Cookie,有的朋友可能会问,这不就是Session么?关闭浏览器就失效。

哈哈,那么Session又是啥呢?

从性质上讲,Session即回话,指一种持续性的,双向的连接。对于web而言,Session指用户在浏览某个网站时,从进入网站到浏览器关闭这段时间的会话。所以,Session实际上是一个特定的时间概念。

PHP的Session默认通过文件方式实现,一般存储于服务器的temp目录,当然也可以通过配置php.ini的session.save_path参数进行更改。

我们打开服务器的temp目录


可以看到很多sess_开头的文件,就是Session。我们通过编辑器打开



哈哈,这是我开发的第一代智能分诊系统,在页面间通过Session传递科室和挂号信息的Session。。。我们看到,其内容结构一般如下:

变量名|类型|:长度:值;

那么Session是如何工作的呢?

我们知道Session是用来存储客户端状态信息的,Session通过一个称为PHPSESSID的Cookie和服务器联系。Session是通过sessionID判断客户端用户的,即文件的文件名。我们打开我去年开发的一个论坛管理系统,通过控制台进行调试。


注意PHPSESSID这个Cookie的value即sessionID。我们现在退出,用户登陆状态的Session注销


我们发现PHPSESSID这个Cookie的value发生了变化。

sessionID实际上是在客户端和服务器端之间通过HTTP Request和HTTP Response传来传去。sessionID按照一定算法生成,必须包含在HTTP Request里面,保证唯一性和随机性,以确保Session的安全。

那么是不是关闭了浏览器,所有Session就都被注销了呢?

如果没有设置Session的生命周期,则SessionID存储在内存中,此时关闭浏览器Session自动注销。而我们已经知道,sessionID是通过PHPSESSID这个Cookie存储在本地的,如下图


那么在浏览器不禁用Cookie的前提下,当然可以通过setcookie()或者seession_set_cookie_params()函数设置Session的生存期,Session过期后,PHP会对其进行回收。

所以,注意哦注意哦,各位,Session并非都是随着浏览器的关闭而消失的!!!!!!!!!

当然,如果你的浏览器禁用Cookie,那么所有所有Session的生存周期都是浏览器进程,关闭浏览器,再次请求页面又将重新生成Session。不过我们也有其他办法进行sessionID的传递,比如URL传参,但是这种方式极度危险,强烈不推荐。此外,还可以通过修改php.ini的session.use_trans_sid参数,实现连接时自己自己添加Session的ID这个在这里暂时不做讨论了,大家想玩就自己尝试吧。

好了,那么现在对于文章开头的几个问题,大家应该都有自己的答案了吧?

第一个问题,虽然Session的确是运行在服务器的,但是sessionID却通过Cookie保存在客户端,所以也不尽然。

第二题,禁止了Cookie,页面的SessionID将无法使用PHPSESSID进行传递,大家可以先登陆某一网站,然后删除浏览器数据,会发现刷新页面或切换页面后将丢失登陆状态,当然我们可以用其他方式替代Cookie进行Session传值,但是很明显,Session会受Cookie禁用的影响。

第三题,存在本地的Cookie确实存在一些不安全因素,但是没人会把安全验证完全放在前端,而且我们知道一般Session是通过sessionID和Cookie进行绑定的,客户端的Cookie一旦被劫持就相当与Session被劫持,服务器验证Cookie的同时将原封不动地完成对Session的验证,所以Session比Cookie安全纯属无稽之谈。

第四题前面讨论过,这里不废话了

第五题,原则上讲是可行的,我们将其称为Cookie劫持,然而我们可以通过在Cookie中加入基于IP等特定信息的参数优化Cookie的验证过程,从而避免这一危险。

好了,我们暂时就聊到这吧,目前在看一些HTTP的东西,有了新的心得,会继续和各位分享,哈哈!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值