会话机制——cookie和session

3,096 阅读7分钟

前言

在日常开发过程中,我们经常会运用会话机制来携带传递一些信息进行校验,交互等行为。这篇文章针对会话机制做一些整理。方便更加清晰地理解客户端与服务端交互过程中在网络协议层面的工作原理。在整理cookie机制和session机制之前。我们有必要对会话的不同状态有一个初步的理解,所以本篇文章将围绕一下几个方面来进行整理。若有理解错误的地方,欢迎指正。

  • 什么是会话机制
  • 会话机制可以解决什么问题(为什么要有会话机制)
  • cookie机制
  • session机制

什么是会话机制?

我们通常说的会话就是客户端和服务端进行交互的这个过程,会话机制就是交互过程遵从的一些规则和工作原理。就好像我们拿起电话从拨号请求到接通到对话再到挂断这样一个完整的过程被称为一次会话。我们常说的“在一个浏览器会话期间”就是指这个浏览器窗口打开到关闭的整个过程。“在一个用户会话期间”就是指用户从开始访问到退出包括中间的一系列操作的一个完整过程。比如说从浏览页面到挑选商品再到结算再到退出这样一个过程。

会话机制解决的问题

在网络协议的不断进化中,为了要满足更多更复杂的操作。会话机制应运而生。我们常说HTTP无状态无连接。其中无连接是指,早期的服务端处理完客户端的请求,受到客户端的应答后立即断开。也就是说客户端每请求一次都会重新建立一个TCP连接。请求完成后服务端就会断开连接释放资源。但是当页面有很多图片等静态资源时,客户端每次请求都建立一次TCP连接就会显得很低效。因此,Keep-Alive被提出来解决这个问题。当HTTP请求头中包含content:Keep-Alive时。客户端与赋予段的连接将不会被断开,当客户端发送另一个请求时就是用这个已经建立好的连接,直到超过Keep-Alive规定的时间连接才会断开。

无状态是指HTTP协议是一个无状态的协议,每个请求都是独立的。这样一来,服务器不知道客户端是什么状态,这严重阻碍了交互式应用程序的开发和使用。在一些特定的应用场景下例如是购物车程序需要知道用户之前都选择了什么商品,但是由于挑选商品和购物车是两个不同的请求,所以购物车程序无法获取挑选好的商品的状态。因此就出现了两种用于保持HTTP状态的技术。也就是cookie机制和session机制。

这里有找到一个很恰当的例子来理解这个问题。我曾经常去的一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠,然而一次性消费5杯咖啡的机会微乎其微,这时就需要某种方式来纪录某位顾客的消费数量。想象一下其实也无外乎下面的几种方案:

  1. 该店的店员很厉害,能记住每位顾客的消费数量,只要顾客一走进咖啡店,店员就知道该怎么对待了。这种做法就是协议本身支持状态。
  2. 发给顾客一张卡片,上面记录着消费的数量,一般还有个有效期限。每次消费时,如果顾客出示这张卡片,则此次消费就会与以前或以后的消费相联系起来。这种做法就是在客户端保持状态。
  3. 发给顾客一张会员卡,除了卡号之外什么信息也不纪录,每次消费时,如果顾客出示该卡片,则店员在店里的纪录本上找到这个卡号对应的纪录添加一些消费信息。这种做法就是在服务器端保持状态。

由于HTTP协议是无状态的,而出于种种考虑也不希望使之成为有状态的,因此,后面两种方案就成为现实的选择。具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。同时我们也看到,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到保存标识的目的,但实际上它还有其他选择。

cookie机制

  • cookie怎样生成
  • cookie有哪些内容
  • cookie怎样使用

cookie怎样生成

正统的cookie是通过扩展HTTP协议来实现的。服务器通过在GTTP响应头中加上一行特殊的指示,浏览器根据只是生成相应的cookie。当然也可以通过客户端代码来生成cookie。例如使用js操作cookie

// cookie都是以键值对的格式存储的,即key=value的格式。各个cookie之间一般是以“;”分隔。
// 以name为例,将此字段种到cookie中,常见操作如下:

//设置cookie  
function setCookie(cname, cvalue, exdays) {  
    var d = new Date();  
    d.setTime(d.getTime() + (exdays*24*60*60*1000));  
    var expires = "expires="+d.toUTCString();   //设置失效日期
    document.cookie = cname + "=" + cvalue + "; " + expires;  
}  

//获取cookie  
function getCookie(cname) {  
    var name = cname + "=";  
    var ca = document.cookie.split(';');  
    for(var i=0; i<ca.length; i++) {  
        var c = ca[i];  
        while (c.charAt(0)==' ') c = c.substring(1);  
        if (c.indexOf(name) != -1) return c.substring(name.length, c.length);  
    }  
    return "";  
}  

//清除cookie    
function clearCookie(name) {    
    setCookie(name, "", -1);    
} 

cookie有哪些内容

cookie包括键名,键值,失效日期,路径和域。键名和键值不做赘述。失效日期如果不设置,则这个cookie的有效期就是浏览器会话期间内,一旦浏览器关闭则此cookie失效。域和路径合起来就是cookie的作用范围。

cookie怎样使用

是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器检查所有存储的cookie,如果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置,则把该cookie附在请求资源的HTTP请求头上发送给服务器。

cookie工作流程:

  1. servlet创建cookie,保存少量数据,发送浏览器。

  2. 浏览器获得服务器发送的cookie数据,将自动的保存到浏览器端。

  3. 下次访问时,浏览器将自动携带cookie数据发送给服务器。

session机制

  • Session怎样生成
  • session的工作原理

Session怎样生成

当客户端请求服务端的时候,服务器的servelet会为当前客户端创建一个session并生成一个sessionId指向这个session。ssionId使用种cookie的方法发送给客户端。大部分session机制都使用会话cookie(即有效期为一个浏览器的会话期间的cookie)来保存sessionId,而关闭浏览器后这个sessionId就消失了,就会导致找不到原来的session。但是由于cookie可以被人为的禁止,必须有其他机制以便在cookie被禁止时仍然能够把sessionid传递回服务器。经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面。

由于服务端无法判断客户端是否已经结束了当前会话所以会在session中设置一个失效时间,一般是30分钟,当距离用户上一次使用session的时间超过这个失效时间,服务器就认为客户端已将停止了此次会话,才会删除session节省存储空间。

session的工作原理

当客户端需要和服务端进行会话的时候,请求发送到服务端。服务端会先检查这个请求里是否包含了一个sessionId。如果已经包含,服务端可以根据此sessionId检索出session来使用。如果检索不出来(session已经失效被删除了)服务端会针对这个sessionId新建一个session。如果客户端请求不包括sessionId这个值,则为此客户端创建一个session并且生成一个与此session相关联的sessionid。写入cookie.