Cookie/Session 笔记
Cookie/Session
为什么要用? 因为HTTP协议是无状态的,一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。简单来说就是HTTP服务器并不知道这个用户是谁、是否登录过等。会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术就是Cookie与Session。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。
1.Cookie
Cookie 的实现机制
Cookie是由客户端保存的小型文本文件,其内容为一系列的键值对。 Cookie是由HTTP服务器设置的,保存在客户端中, 在用户访问其他页面时,会在HTTP请求中附上该服务器之前设置的Cookie。那么Cookie是怎样工作的呢?下面给出整个Cookie的传递流程:
-
浏览器向某个URL发起HTTP请求(可以是任何请求,比如GET一个页面、POST一个登录表单等)
对应的服务器收到该HTTP请求,并计算应当返回给浏览器的HTTP响应。 -
HTTP响应包括请求头和请求体两部分,在响应头加入Set-Cookie字段,它的值是要设置的Cookie。
-
浏览器收到来自服务器的HTTP响应。浏览器在响应头中发现Set-Cookie字段,就会将该字段的值保存在内存或者硬盘中。
cookie的内容主要包括:名字,值,过期时间,路径和域。路径与域一起构成cookie的作用范围。若不设置过期时间,则表示这个cookie的生命期为浏览器会话期间,关闭浏览器窗口,cookie就消失。这种生命期为浏览器会话期的cookie被称为会话cookie。会话cookie一般不存储在硬盘上而是保存在内存里,当然这种行为并不是规范规定的。若设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie仍然有效直到超过设定的过期时间。浏览器下次给该服务器发送HTTP请求时, 会将服务器设置的Cookie附加在HTTP请求的头字段Cookie中。
浏览器可以存储多个域名下的Cookie,但只发送当前请求的域名曾经指定的Cookie, 这个域名也可以在Set-Cookie字段中指定)。服务器收到这个HTTP请求,发现请求头中有Cookie字段, 便知道之前就和这个用户打过交道了。过期的Cookie会被浏览器删除。
Cookie 的安全隐患
Cookie提供了一种手段使得HTTP请求可以附加当前状态, 现今的网站也是靠Cookie来标识用户的登录状态的:
- 用户提交用户名和密码的表单,这通常是一个POST HTTP请求。
- 服务器验证用户名与密码,如果合法则返回200(OK)并设置Set-Cookie为authed=true。
- 浏览器存储该Cookie。
- 浏览器发送请求时,设置Cookie字段为authed=true。
- 服务器收到第二次请求,从Cookie字段得知该用户已经登录。 按照已登录用户的权限来处理此次请求。
这里面的问题在哪里?
我们知道可以发送HTTP请求的不只是浏览器,很多HTTP客户端软件(包括curl、Node.js)都可以发送任意的HTTP请求,可以设置任何头字段。 假如我们直接设置Cookie字段为authed=true并发送该HTTP请求, 服务器岂不是被欺骗了?这种攻击非常容易,Cookie是可以被篡改的!
Cookie 防篡改机制
服务器可以为每个Cookie项生成签名,由于篡改Cookie后无法生成对应的签名, 服务器便可以得知用户对Cookie进行了篡改。一个简单的校验过程可能是这样的:
在服务器中配置一个不为人知的字符串(我们叫它Secret),比如:xdsafg458。当服务器需要设置Cookie时(比如authed=false),不仅设置authed的值为false, 在值的后面进一步设置一个签名,最终设置的Cookie是authed=false|6hTiBl7lVpd1P。签名6hTiBl7lVpd1P是这样生成的:Hash(xdsafg458’+‘false’)。假设用户在发送HTTP请求时,篡改了authed值,设置头字段Cookie: authed=true|???。 因为用户不知道Secret,无法生成签名,只能随便填一个。服务器收到HTTP请求,发现Cookie: authed=true|???。服务器开始进行校验: Hash(‘true’+‘x$sfz32’),便会发现用户提供的签名不正确。使得服务器得以知道Cookie被篡改,然而并未结束。
因为Cookie是明文传输的, 只要服务器设置过一次authed=true|xxxx我不就知道true的签名是xxxx了么, 以后就可以用这个签名来欺骗服务器了。因此Cookie中最好不要放敏感数据。 一般来讲Cookie中只会放一个Session Id,而Session存储在服务器端。
2.Session
Session 的实现机制
Session 是保存在服务器端的,避免了在客户端Cookie中存储敏感数据。 Session 可以存储在HTTP服务器的内存中,也可以存在内存数据库(如redis)中。
session的创建:
当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了sessionId,如果已包含则说明以前已经为此客户端创建过session,服务器就按照sessionId把这个session检索出来使用,如果客户端请求不包含sessionId,则为此客户端创建一个session并且生成一个与此session相关联的sessionId,sessionId的值是一个既不会重复,又不容易被找到规律以仿造的字符串,这个sessionId将被在本次响应中返回给客户端保存。
通过Session ID,服务器进行放篡改验证。如果通过了验证,可以从服务端中取出对应的用户对象, 敏感数据(比如authed=true)都存储在这个用户对象中。
禁用cookie:
如果客户端禁用了cookie,通常有两种方法实现session而不依赖cookie。
- URL重写,就是把sessionId直接附加在URL路径的后面。
- 表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。比如:
<form name="testform" action="/xxx">
<input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
<input type="text">
</form>
cookie 和session 的区别:
- cookie数据存放在客户的浏览器上,session数据放在服务器上。
- cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。 - 存储数据量方面:session 能够存储任意的 java 对象,cookie 只能存储 String 类型的对象
- 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
- Session过多时会消耗服务器资源,大型网站会有专门Session服务器,Cookie存在客户端没问题。
- 域的支持范围不一样,比方说a.com的Cookie在a.com下都能用,aaa.test.com的Session在bbb.test.com不能用,解决这个问题的办法是JSONP或者跨域资源共享。
下一篇: Python新手入门最容易犯的错误总结
推荐阅读
-
PHP中STDIN, STDOUT, STDERR的重定向 博客分类: PHP开发Linux学习笔记
-
ASP.NET中在一般处理程序中使用session的简单介绍
-
Cookie/Session 笔记
-
cookie和session学习
-
PHP 5.3.0以上推荐使用mysqlnd驱动 博客分类: Linux学习笔记PHP开发
-
高并发下iptables丢包导致网络变慢解决方法 博客分类: Linux学习笔记
-
深入分析Redis Server went away产生的原因 博客分类: Linux学习笔记PHP开发
-
自己学习c++过程中写下的笔记,只做基础了解使用
-
SSO(Single Sign-On) 调查笔记 博客分类: sso
-
JavaWeb学习笔记(六)Cookie 和 Session