|
1 | 1 | #6.1 session和cookie
|
| 2 | +session和cookie是网站浏览中较为常见的两个概念,也是比较难以辨析的两个概念,但它们在用户浏览需要认证的服务页面以及页面统计中却相当关键。首先我们先来了解一下session和cookie怎么来的?我们先来考虑一个问题: |
| 3 | + |
| 4 | +如何抓取一个访问受限的网页?如新浪微博好友的主页,个人微博页面等。 |
| 5 | + |
| 6 | +显然,通过浏览器,我们可以手动输入用户名密码来访问页面,而所谓的“抓取”,其实就是使用程序来模拟完成同样的工作,因此我们需要了解“登陆”过程中到底发生了什么。 |
| 7 | + |
| 8 | +对于未登录的用户系统跳转到了登陆页面,用户输入用户名和密码之后POST给远端的服务器,通过验证之后跳转到了微博首页,那么服务器如何验证我们访问其他受限制的页面呢?由于HTTP协议是无状态的,显然,服务器不可能知道我们上一秒刚刚登录成功。当然,最简单的解决方案就是所有的请求里面都带上用户名和密码,这样虽然可行,但大大加重了服务器的负担(对于每个request都需要到数据库验证),也大大降低了用户体验(每个页面都需要重新输入用户名密码,每个页面都带有登录表单). |
| 9 | + |
| 10 | +所以自然就产生了第一种解决方案:cookie,简而言之就是在本地计算机保存一些用户操作的历史信息(当然包括登录信息),并在用户再次访问该站点时浏览器通过HTTP协议将本地cookie内容发送给服务器,从而完成验证,或继续上一步操作。 |
| 11 | + |
| 12 | +另一种解决方案:session,简而言之就是在服务器上保存用户操作的历史信息。但该方式下,仍然需要将发送请求的客户端与session对象进行对应,所以可以借助cookie机制来获取客户端的标识(即session id),也可以通过GET方式将id提交给服务器。session id,即服务器上session对象文件的名称,由服务器负责产生,保证随机性与唯一性,相当于一个随机密钥,避免在握手或传输中暴露用户真实密码。 |
| 13 | + |
| 14 | +##cookie |
| 15 | +Cookie是客户端的存储空间,由浏览器来维持。cookie是一小段文本信息,伴随着用户请求和页面在Web服务器和浏览器之间传递。用户每次访问站点时,Web应用程序都可以读取cookie包含的信息。打开我们的浏览器设置,里面有cookie隐私数据选项,打开我们可以看到很多我们访问网站的cookie信息,如下图所示: |
| 16 | + |
| 17 | + |
| 18 | + |
| 19 | +cookie是有时间限制的,根据生命期不同分成两种cookie:会话cookie和持久cookie; |
| 20 | + |
| 21 | +如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览会话期的cookie被称为会话cookie。会话cookie一般不保存在硬盘上而是保存在内存里。 |
| 22 | + |
| 23 | +如果设置了过期时间(setMaxAge(60*60*24)),浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间。存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存的cookie,不同的浏览器有不同的处理方式。 |
| 24 | + |
| 25 | + |
| 26 | +###Go设置cookie |
| 27 | +Go语言中设置cookie在net/http包中已经有这样的函数,我们来看一下: |
| 28 | + |
| 29 | +http.SetCookie(w ResponseWriter, cookie *Cookie) |
| 30 | + |
| 31 | +w表示需要写入的response,cookie是一个struct,让我们来看一下cookie对象是怎么样的 |
| 32 | + |
| 33 | +type Cookie struct { |
| 34 | + Name string |
| 35 | + Value string |
| 36 | + Path string |
| 37 | + Domain string |
| 38 | + Expires time.Time |
| 39 | + RawExpires string |
| 40 | + |
| 41 | + // MaxAge=0 means no 'Max-Age' attribute specified. |
| 42 | + // MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0' |
| 43 | + // MaxAge>0 means Max-Age attribute present and given in seconds |
| 44 | + MaxAge int |
| 45 | + Secure bool |
| 46 | + HttpOnly bool |
| 47 | + Raw string |
| 48 | + Unparsed []string // Raw text of unparsed attribute-value pairs |
| 49 | +} |
| 50 | + |
| 51 | +我们来看一个例子,如何设置cookie |
| 52 | + |
| 53 | +expiration := *time.LocalTime() |
| 54 | +expiration.Year += 1 |
| 55 | +cookie := http.Cookie{Name: "browserID", Value: "my value", Expires: expiration} |
| 56 | +http.SetCookie(w, &cookie) |
| 57 | + |
| 58 | + |
| 59 | +###Go读取cookie |
| 60 | +上面的例子演示了如何设置cookie数据,我们这里来演示一下如何读取cookie |
| 61 | + |
| 62 | +cookie, _ := r.Cookie("browserID") |
| 63 | +fmt.Fprint(w, cookie) |
| 64 | + |
| 65 | +还有另外一种读取方式 |
| 66 | + |
| 67 | +for _, cookie := range r.Cookies() { |
| 68 | +fmt.Fprint(w, cookie.Name) |
| 69 | +} |
| 70 | + |
| 71 | +##session |
| 72 | + |
| 73 | +session,中文经常翻译为会话,其本来的含义是指有始有终的一系列动作/消息,比如打电话是从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session。然而当session一词与网络协议相关联时,它又往往隐含了“面向连接”和/或“保持状态”这样两个含义。 |
| 74 | + |
| 75 | +session在Web开发环境下的语义又有了新的扩展,它的含义是指一类用来在客户端与服务器端之间保持状态的解决方案。有时候Session也用来指这种解决方案的存储结构。 |
| 76 | + |
| 77 | +session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存息。 |
| 78 | + |
| 79 | +但程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否包含了一个session标识-称为session id,如果已经包含一个session id则说明以前已经为此客户创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个,这种情况可能出现在服务端已经删除了该用户对应的session对象,但用户人为地在请求的URL后面附加上一个JSESSION的参数)。如果客户请求不包含session id,则为此客户创建一个session并且同时生成一个与此session相关联的session id,这个session id将在本次响应中返回给客户端保存。 |
| 80 | + |
| 81 | +session机制本身并不复杂,然而其实现和配置上的灵活性却使得具体情况复杂多变。这也要求我们不能把仅仅某一次的经验或者某一个浏览器,服务器的经验当作普遍适用的。 |
| 82 | + |
| 83 | +##小结 |
| 84 | + |
| 85 | +如上文所述,session和cookie的目的相同,都是为了克服http协议无状态的缺陷,但完成的方法不同。session通过cookie,在客户端保存session id,而将用户的其他会话消息保存在服务端的session对象中,与此相对的,cookie需要将所有信息都保存在客户端。因此cookie存在着一定的安全隐患,例如本地cookie中保存的用户名密码被破译,或cookie被其他网站收集(例如:1. appA主动设置域B cookie,让域B cookie获取;2. XSS,在appA上通过javascript获取document.cookie,并传递给自己的appB)。 |
| 86 | + |
| 87 | + |
| 88 | +通过上面的一些简单介绍我们了解了cookie和session的一些基础知识,知道他们之间的联系和区别,所以,知其然,还需要知其所以然。磨刀不误砍柴工,授人以渔,做web开发之前,有必要将一些必要知识了解清楚,才不会在用到时捉襟见肘,或是在调bug时候如无头苍蝇乱转。 |
| 89 | + |
2 | 90 | ## links
|
3 | 91 | * [目录](<preface.md>)
|
4 | 92 | * 上一节: [session和数据存储](<6.md>)
|
|
0 commit comments