Web 开发中一个很重要的议题就是如何做好用户的整个浏览过程的控制,因为 HTTP 协议是无状态的,所以用户的每一次请求都是无状态的,我们不知道在整个 Web 操作过程中哪些连接与该用户有关,我们应该如何来解决这个问题呢?Web 里面经典的解决方案是 cookie 和 session,cookie 机制是一种客户端机制,把用户数据保存在客户端,而 session 机制是一种服务器端的机制,服务器使用一种类似于散列表的结构来保存信息,每一个网站访客都会被分配给一个唯一的标志符,即 sessionID, 它的存放形式无非两种:要么经过 url 传递,要么保存在客户端的 cookies 里。当然,你也可以将 Session 保存到数据库里,这样会更安全,但效率方面会有所下降。
session 和 cookie 是网站浏览中较为常见的两个概念,也是比较难以辨析的两个概念,但它们在浏览需要认证的服务页面以及页面统计中却相当关键。我们先来了解一下 session 和 cookie 怎么来的?考虑这样一个问题:
如何抓取一个访问受限的网页?如新浪微博好友的主页,个人微博页面等。
显然,通过浏览器,我们可以手动输入用户名和密码来访问页面,而所谓的 “抓取”,其实就是使用程序来模拟完成同样的工作,因此我们需要了解 “登陆” 过程中到底发生了什么。
当用户来到微博登陆页面,输入用户名和密码之后点击 “登录” 后浏览器将认证信息 POST 给远端的服务器,服务器执行验证逻辑,如果验证通过,则浏览器会跳转到登录用户的微博首页,在登录成功后,服务器如何验证我们对其他受限制页面的访问呢?因为 HTTP 协议是无状态的,所以很显然服务器不可能知道我们已经在上一次的 HTTP 请求中通过了验证。当然,最简单的解决方案就是所有的请求里面都带上用户名和密码,这样虽然可行,但大大加重了服务器的负担(对于每个 request 都需要到数据库验证),也大大降低了用户体验 (每个页面都需要重新输入用户名密码,每个页面都带有登录表单)。既然直接在请求中带上用户名与密码不可行,那么就只有在服务器或客户端保存一些类似的可以代表身份的信息了,所以就有了 cookie 与 session。
cookie,简而言之就是在本地计算机保存一些用户操作的历史信息(当然包括登录信息),并在用户再次访问该站点时浏览器通过 HTTP 协议将本地 cookie 内容发送给服务器,从而完成验证,或继续上一步操作。
session,简而言之就是在服务器上保存用户操作的历史信息。服务器使用 session id 来标识 session,session id 由服务器负责产生,保证随机性与唯一性,相当于一个随机密钥,避免在握手或传输中暴露用户真实密码。但该方式下,仍然需要将发送请求的客户端与 session 进行对应,所以可以借助 cookie 机制来获取客户端的标识(即 session id),也可以通过 GET 方式将 id 提交给服务器。