安全 详解 Cookie 和 Session 关系和区别

HongJack · 发布于 2017年06月26日 · 最后由 fengkuok 回复于 2017年06月28日 · 1742 次阅读
28010

作者 | 个推web前端架构师 姜季廷

在技术面试中,经常被问到“说说Cookie和Session的区别”,大家都知道,Session是存储在服务器端的,Cookie是存储在客户端的,然而如果让你更详细地说明,你能说出几点?今天个推君就和大家谈谈“Cookie和Session”的那些事儿。

Cookie是什么?

从它的词语本身含义来看: Cookie: n. 饼干;小甜点 N-COUNT A cookie is a piece of computer software which enables a website you have visited to recognize you if you visit it again. 再次访问某一网站时,能令网站识别访问人的计算机软件。

Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息。如何识别特定的客户呢?cookie就可以做到。每次HTTP请求时,客户端都会发送相应的Cookie信息到服务端。它的过期时间可以任意设置,如果你不主动清除它,在很长一段时间里面都可以保留着,即便这之间你把电脑关机了。

既然它是存储在客户端的,换句话说通过某些手法我就可以篡改本地存储的信息来欺骗服务端的某些策略,那该怎么办呢?我们先按下不表,来看看另外一位朋友 —— Session。

Session是什么?

同样,我们先来看看释义: Session: 普通释义:n. 会议;(法庭的)开庭;(议会等的)开会;学期;讲习会 计算机释义:会话

Session是在无状态的HTTP协议下,服务端记录用户状态时用于标识具体用户的机制。它是在服务端保存的用来跟踪用户的状态的数据结构,可以保存在文件、数据库或者集群中。在浏览器关闭后这次的Session就消失了,下次打开就不再拥有这个Session。其实并不是Session消失了,而是Session ID变了,服务器端可能还是存着你上次的Session ID及其Session 信息,只是他们是无主状态,也许一段时间后会被删除。

实际上Cookie与Session都是会话的一种方式。它们的典型使用场景比如“购物车”,当你点击下单按钮时,服务端并不清楚具体用户的具体操作,为了标识并跟踪该用户,了解购物车中有几样物品,服务端通过为该用户创建Cookie/Session来获取这些信息。

如果你的站点是多节点部署,使用Nginx做负载均衡,那么有可能会出现Session丢失的情况(比如,忽然就处于未登录状态)。这时可以使用IP负载均衡(IP绑定 ip_hash,每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决Session的问题),或者将Session信息存储在集群中。在大型的网站中,一般会有专门的Session服务器集群,用来保存用户会话,这时可以使用缓存服务比如Memcached或者Redis之类的来存放Session。

目前大多数的应用都是用 Cookie 实现Session跟踪的。第一次创建Session时,服务端会通过在HTTP协议中反馈到客户端,需要在 Cookie 中记录一个Session ID,以便今后每次请求时都可分辨你是谁。有人问,如果客户端的浏览器禁用了 Cookie 怎么办?建议使用URL重写技术进行会话跟踪,即每次HTTP交互,URL后面都被附加上诸如 sid=xxxxx 的参数,以便服务端依此识别用户。

换个姿势~

客户端和服务端之间的通信交流,可以这样简单理解: 比如当你在个推技术分享沙龙上觉得某位讲师讲得很好,在会后问了他几个问题,他对你这些问题进行了回答,这就是一个会话。但这个讲师太受欢迎,于是工作人员收集问题,并给每个提问者一个号码牌,讲师按照号码牌依次给出相应解答并告诉相应的人。这就是Session。一段时间后,当你再次遇见这位讲师,他发现你身上有上次回复你的答案,知晓你是那个好学的程序猿。于是你欣喜若狂,哇塞,讲师居然认出我了,这就是Cookie,你的小甜点。客户端好比听课的技术爱好者,服务端就是这位讲师。

Cookie还可以在一些方便用户的场景下使用。比如你某次登陆过一个网站,下次登录的时候不想再次输入账号了,怎么办?这个信息可以被写到Cookie里面,当访问网站时,网站页面的脚本可以读取这个信息,自动填写用户名,方便用户使用,给用户一点甜头。

总结语:

1、Cookie 在客户端(浏览器),Session 在服务器端。 2、Cookie的安全性一般,他人可通过分析存放在本地的Cookie并进行Cookie欺骗。在安全性第一的前提下,选择Session更优。重要交互信息比如权限等就要放在Session中,一般的信息记录放Cookie就好了。 3、单个Cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个Cookie。 4、Session 可以放在 文件、数据库或内存中,比如在使用Node时将Session保存在redis中。由于一定时间内它是保存在服务器上的,当访问增多时,会较大地占用服务器的性能。考虑到减轻服务器性能方面,应当适时使用Cookie。 5、Session 的运行依赖Session ID,而 Session ID 是存在 Cookie 中的,也就是说,如果浏览器禁用了 Cookie,Session 也会失效(但是可以通过其它方式实现,比如在 url 中传递 Session ID)。 6、用户验证这种场合一般会用 Session。因此,维持一个会话的核心就是客户端的唯一标识,即Session ID。

题外话,那么话说Session Cookie能被篡改么? 理论上可以,只要改变了连接时的Session ID 就可以了~

共收到 28 条回复
4215

rails的session依赖于cookie么?我理解好像是依赖的。

96

我有几个纯前端应用,如何做能让用户在这几个应用间无需多次登陆?

1

“大家都知道,Session是存储在服务器端的,Cookie是存储在客户端的”

面试 Rails 职位这么回答的话,可以回家等通知了。

27936
1Rei 回复

哈哈哈哈哈哈哈哈哈哈哈哈

27936
4215chenge 回复

默认基于cookie,你可以配置的,甚至存在数据库里

4215
27936ecnelises 回复

我理解是需要配合吧。如果没有cookie,服务器怎么知道是哪个session呢?需要session id吧。

27936
4215chenge 回复

CookieBased session 的原理是把session转码之后直接存cookie里,再加上一个签名用于验证,类似jwt

96

jwt不适用于存放敏感信息, session则没有这样的问题, 并不认同将session转码存放cookie,这样的理解

3035
1Rei 回复

哈哈哈~ 毕竟头图上就放了两个 php 嘛,肯定是说的 php 里的情况咯

3035
32wayne712 回复

你的不认同可能源自你已经将 session 与 敏感信息 划上了等号,但是我觉得这样的理解是有待商榷的 如果你在知道 CookieBased session 并不能阻止其他人看到其中的信息的情况下,不在里面放入敏感信息不就好了

挺多框架默认方案就是 CookieBased session,为什么呢? 因为成本低呀。 而且也没有哪一家在文档里面说了 session 可以安心的放入敏感信息的吧

1
3035IChou 回复

Rails 现在的 cookie store 是加密的,可以放敏感信息,主要限制还是体积。

3035
1Rei 回复

咦 我记得是没有的呢, 难道什么时候改了?

15420
32jetspeed 回复

单点登入

1
3035IChou 回复

If you only have secret_token set, your cookies will be signed, but not encrypted. This means a user cannot alter their user_id without knowing your app's secret key, but can easily read their user_id. This was the default for Rails 3 apps.
If you have secret_key_base set, your cookies will be encrypted. This goes a step further than signed cookies in that encrypted cookies cannot be altered or read by users. This is the default starting in Rails 4.

http://api.rubyonrails.org/classes/ActionDispatch/Session/CookieStore.html

12637

本文的各种疏漏,以及排版,都无力吐槽

3035

昂~ 查了下 果然是我理解错了 之前有个 php 的项目需要取到 Rails 的 cookie 里的内容,就去实现了一套 php 下面的 ruby_ marshal 序列化和反序列化。从那以后我就一直以为 Rails 的 session 只有 signature 没有真正的加密,原来只是我们那个项目特意关闭了加密而已 😂

PS: 顺便贴下 php 实现 ruby_ marshal 的地址,万一有人感兴趣呢,哈哈~ https://github.com/sudiyi/ruby_marshal

96
12637marksloan 回复

哪些疏漏,可以修正出来让大家学习一下。

28010
12637marksloan 回复

😁 欢迎提修改意见哦~

28010
4215chenge 回复

这不是在面试的时候说的哦~

28010
32jetspeed 回复

由于网关处理鉴权,将登录的用户信息以参数形式往下传~同域名的话,只要做一层统一网关就好啦

96

参数写在url里?别人可以看到了?

9980
1Rei 回复

666!!!!

1107
3035IChou 回复

Rails 的 Session 还可以以 JSON 形式存在的 http://blog.bigbinary.com/2014/12/23/migrating-existing-session-cookies-while-upgrading-to-rails-4-1-and-above.html Rails 4.1 后这样是默认了

17004

“大家都知道,Session是存储在服务器端的,Cookie是存储在客户端的”,我学了假的session假的cookie

3930
1Rei 回复

session 在服务器端,cookie 在客户端,这个理解有问题吗?

9936
3930fengkuok 回复

HTTP是无状态的协议,请求之间记录用户状态需要用到Session机制,但存储Session的方式有多种,可以存储在服务器,例如数据库、文件,也可以存储在cookie中(rails默认方式)

3930
1Rei 回复

CookieStore , 明白了,多谢!

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册