Files
build-web-application-with-…/6.1.md
2012-09-17 23:29:38 +08:00

98 lines
7.4 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#6.1 session和cookie
session和cookie是网站浏览中较为常见的两个概念也是比较难以辨析的两个概念但它们在用户浏览需要认证的服务页面以及页面统计中却相当关键。首先我们先来了解一下session和cookie怎么来的我们先来考虑一个问题
如何抓取一个访问受限的网页?如新浪微博好友的主页,个人微博页面等。
显然,通过浏览器,我们可以手动输入用户名密码来访问页面,而所谓的“抓取”,其实就是使用程序来模拟完成同样的工作,因此我们需要了解“登陆”过程中到底发生了什么。
对于未登录的用户系统跳转到了登陆页面用户输入用户名和密码之后POST给远端的服务器通过验证之后跳转到了微博首页那么服务器如何验证我们访问其他受限制的页面呢由于HTTP协议是无状态的显然服务器不可能知道我们上一秒刚刚登录成功。当然最简单的解决方案就是所有的请求里面都带上用户名和密码这样虽然可行但大大加重了服务器的负担对于每个request都需要到数据库验证也大大降低了用户体验(每个页面都需要重新输入用户名密码,每个页面都带有登录表单).
所以自然就产生了第一种解决方案cookie简而言之就是在本地计算机保存一些用户操作的历史信息当然包括登录信息并在用户再次访问该站点时浏览器通过HTTP协议将本地cookie内容发送给服务器从而完成验证或继续上一步操作。
另一种解决方案session简而言之就是在服务器上保存用户操作的历史信息。但该方式下仍然需要将发送请求的客户端与session对象进行对应所以可以借助cookie机制来获取客户端的标识即session id也可以通过GET方式将id提交给服务器。session id即服务器上session对象文件的名称由服务器负责产生保证随机性与唯一性相当于一个随机密钥避免在握手或传输中暴露用户真实密码。
##cookie
Cookie是客户端的存储空间由浏览器来维持。cookie是一小段文本信息伴随着用户请求和页面在Web服务器和浏览器之间传递。用户每次访问站点时Web应用程序都可以读取cookie包含的信息。打开我们的浏览器设置里面有cookie隐私数据选项打开我们可以看到很多我们访问网站的cookie信息如下图所示
![](images/6.1.cookie.png?raw=true)
cookie是有时间限制的根据生命期不同分成两种cookie会话cookie和持久cookie
如果不设置过期时间则表示这个cookie生命周期为浏览器会话期间只要关闭浏览器窗口cookie就消失了。这种生命期为浏览会话期的cookie被称为会话cookie。会话cookie一般不保存在硬盘上而是保存在内存里。
如果设置了过期时间(setMaxAge(60*60*24))浏览器就会把cookie保存到硬盘上关闭后再次打开浏览器这些cookie依然有效直到超过设定的过期时间。存储在硬盘上的cookie可以在不同的浏览器进程间共享比如两个IE窗口。而对于保存在内存的cookie不同的浏览器有不同的处理方式。
  
###Go设置cookie
Go语言中设置cookie在net/http包中已经有这样的函数我们来看一下
http.SetCookie(w ResponseWriter, cookie *Cookie)
w表示需要写入的responsecookie是一个struct让我们来看一下cookie对象是怎么样的
type Cookie struct {
Name string
Value string
Path string
Domain string
Expires time.Time
RawExpires string
// MaxAge=0 means no 'Max-Age' attribute specified.
// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
// MaxAge>0 means Max-Age attribute present and given in seconds
MaxAge int
Secure bool
HttpOnly bool
Raw string
Unparsed []string // Raw text of unparsed attribute-value pairs
}
我们来看一个例子如何设置cookie
expiration := *time.LocalTime()
expiration.Year += 1
cookie := http.Cookie{Name: "username", Value: "astaxie", Expires: expiration}
http.SetCookie(w, &cookie)
  
###Go读取cookie
上面的例子演示了如何设置cookie数据我们这里来演示一下如何读取cookie
cookie, _ := r.Cookie("username")
fmt.Fprint(w, cookie)
还有另外一种读取方式
for _, cookie := range r.Cookies() {
fmt.Fprint(w, cookie.Name)
}
我们看到通过request获取cookie非常方便。
##session
session中文经常翻译为会话其本来的含义是指有始有终的一系列动作/消息比如打电话是从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session。然而当session一词与网络协议相关联时它又往往隐含了“面向连接”和/或“保持状态”这样两个含义。
session在Web开发环境下的语义又有了新的扩展它的含义是指一类用来在客户端与服务器端之间保持状态的解决方案。有时候Session也用来指这种解决方案的存储结构。
session机制是一种服务器端的机制服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存息。
但程序需要为某个客户端的请求创建一个session的时候服务器首先检查这个客户端的请求里是否包含了一个session标识称为session id如果已经包含一个session id则说明以前已经为此客户创建过session服务器就按照session id把这个session检索出来使用(如果检索不到可能会新建一个这种情况可能出现在服务端已经删除了该用户对应的session对象但用户人为地在请求的URL后面附加上一个JSESSION的参数)。如果客户请求不包含session id则为此客户创建一个session并且同时生成一个与此session相关联的session id这个session id将在本次响应中返回给客户端保存。
session机制本身并不复杂然而其实现和配置上的灵活性却使得具体情况复杂多变。这也要求我们不能把仅仅某一次的经验或者某一个浏览器服务器的经验当作普遍适用的。
##小结
如上文所述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
通过上面的一些简单介绍我们了解了cookie和session的一些基础知识知道他们之间的联系和区别所以知其然还需要知其所以然。磨刀不误砍柴工授人以渔做web开发之前有必要将一些必要知识了解清楚才不会在用到时捉襟见肘或是在调bug时候如无头苍蝇乱转。
## links
* [目录](<preface.md>)
* 上一节: [session和数据存储](<6.md>)
* 下一节: [Go如何使用session](<6.2.md>)
## LastModified
* $Id$