Cookie和Session详解

2018-01-19 10:17:00
linefo
原创
798


开发中一直在用cookie和session,但一直处在知其然而不知其所以然的状态,这次认真做一下整理。

这个现在已经是网站必有的技术了,并且是一种通用的标准,不用担心语言上的差异。


为什么需要


HTTP是无状态的,这里的无状态可以理解为,客户端和服务器的会话不会被保留。

以HTTP本身的机制来说,没有用户身份这个概念,两次的访问是否来源与同一个用户,它不关心。

但我们却关心访问是否来源于同一用户,我们必须在服务器识别出用户身份,比如我们希望保留登录的状态,a用户和b用户访问的用户中心,里面的信息肯定是不一样的。

cookie和session的使用就是为了解决这个。


cookie是什么


cookie是通过浏览器,保存在用户电脑上的特定信息,需要浏览器的支持。


比如我们要实现这样一个功能:用户未登录时,可以把商品先添加到购物车中。

工作流程:(1)用户操作添加购物车时,将商品列表告诉服务器,服务器接收到以后,把该商品列表发给用户浏览器,并告诉浏览器在用户电脑上用cookie存储下来;(2)用户每次访问该网站时,都会把存储的和该网站相关的cookie发给服务器,其中就包括了存储的购物车列表,服务器接收到这个购物车列表以后,在页面中显示列表信息给用户看。(3)如果没有设置过期时间,关掉浏览器后这些cookie就会被删除,设置过期时间以后,即使关闭浏览器,在过期之前cookie仍有效。


cookie实际上保存成文件或在浏览器使用的内存中的,实际保存的格式要看浏览器的机制。

设置有过期时间的肯定会保存一份文件形式,而运行中的会在浏览器使用的内容中驻留。


cookie发送给服务器时,是放在HTTP头部信息中的:


在浏览器允许的情况下,JavaScript脚本也可以读取cookie的内容。


cookie有一些重要的相关设置:


过期时间


如果不设置cookie过期时间,cookie会在会话结束后销毁。


domain 选项


这个设置cookie有效的域名,如果设置成 www.a.com 的话,在 m.a.com 是不生效的。

如果设置成 a.com 那么在 www.a.com 和 m.a.com 都生效。


path 选项


设置 cookie 在指定的 path(URL路径)中才生效,是对domain 选项的补充。比如设置 path 的值为 /blog , 那么当url中含有该值才生效,如 www.a.com/blog/xx.html。


secure 选项


标记安全级别,设置以后,只有ssl或者https的请求中,cookie才生效


HTTP-Only


告诉浏览器该 cookie 绝不能通过 JavaScript访问


session是什么


我们经常会使用session去保持用户登录状态,它是保存在服务器上的一些特定信息。


session的工作机制是这样的:启用后,在服务器上会针对不同的访问用户生成身份信息,此时无论你用session储存什么值,都会带上这一段身份信息;同时会让用户浏览器储存一个身份标识(session_id),在用户访问网站时都会携带这个标识,服务器根据这个标识去获取对应身份信息的值;


网上总有人说session实际上是cookie,这是不正确的说法,正确的理解是:session和cookie是不同的,但它们一般来说确实是紧密相关,因为session在客户端存储的身份标识(session_id)是用cookie存储的,发送给服务器时也是以cookie值的形式放在HTTP头部信息中的。


如果浏览器禁用cookie是不是session就不能用了呢?不能简单这么说,如果session_id在客户端的存储形式不是cookie,发送时也不以cookie值的形式(比如做一个隐藏的表单域)发送,服务器也是能够获得这个session_id并处理的,只是这样会比较麻烦。


扩展1:多域名共用session


以PHP为例(其他WEB语言原理一致,但实现方法有区别)。


经常用作单点登录:


在浏览购物网站时,我们登录了淘宝网(taobao.com),而天猫(tmall.com)也会显示我们在登录状态。说明对我来说,session实现了在淘宝和天猫的共享。而一般来说,即便是同一个用户(同浏览器)在访问,不同域名的session值是互相独立的,这两个网站是怎么实现的呢?


上面我们说过,服务器是通过一个sessionid去获取session值的,a用户和b用户访问我的同一个网站时,网站先从浏览器cookie中获得a和b的不同sessionid,然后根据sessionid去读不同的session值。


照这样理解,如果同一个用户(同浏览器)在访问我不同网站时,服务器拿到的如果是同样的sessionid,不就可以实现session共享了吗。


提供一个简单的解决思路:

如果用户登录了我们的第一个网站,那么在不携带sessionid的情况下访问第二个网站时,做一个内部重定向访问第一个网站,将获取的sessionid(可加密)附加在url上做重定向回第二个网站即可——》在php中(第二个网站)处理时,先用seesion_id("sessionid值")预设置好,再用session_start()开启session,此时用户在第二个网站中会获得和在第一个网站一样的session值。


我们知道服务器是把session值放在服务器文件中的,如果两个域名在不同的服务器下(同时还有服务器集群,每次访问同一个域名也可能会访问不同的服务器),就无法实现session共享。所以一般我们会把session存到redis等缓存中,处理方式也很简单,在php.ini设置中,设置特定的配置项:

session.save_handler = redis;

session.save_path = "tcp://redis服务地址:端口?auth=密码"

文章分类
联系我们
联系人: Mr.Chen
QQ: 185391277