在浏览网页时,很多页面是需要登录的,但是我们知道HTTP协议是无状态协议,那么我们在网站的各个网页间跳转时,为什么不需要重新登录账号呢?这就是Session和Cookies的功劳了,接下来,让我们一步一步解析Session和Cookies是什么。
目录:
- 1.静态网页和动态网页
- 2.无状态的HTTP协议
- 3.原理剖析
- 4.常见误区
1.静态网页和动态网页:
网页内容由纯HTML编写,文字,图片等内容均通过写好的HTML代码来指定,这种页面叫做静态网页。 优点:加载速度快,编写简单。 缺点:可维护性差,不能根据URL灵活显示内容,比如:若想给url传入一个name参数,让其在网页显示,静态网页无法实现。
于是动态网页产生了,它可以根据URL中参数的变化进行动态解析,关联数据库并呈现不同的页面内容,非常灵活多变。现在我们遇到的网站大多是动态网站,他们由JS,Python,JSP等语言编写,功能比静态网页强大多了。
此外,动态网站还可以实现用户登录和注册功能。生活中,很多页面需要登录才可以查看,那么输入用户名和密码进行登录,肯定是拿到了一种类似凭证的东西,有了它,才可以保持登录状态,访问登录之后才能看到的页面。
这种凭证就是Session和Cookies的产物。
2.无状态的HTTP协议
探究凭证前,我们需要了解HTTP一个特点:无状态。
HTTP无状态指:HTTP协议对事务处理是没有记忆能力的, 也就是说服务器不知道客户端是什么状态。当我们向服务器发送请求后,服务器解析此请求,然后返回对应的相应,服务器负责完成整个过程。 这个过程是完全独立的,服务器不会记录前后状态的变化,也就是缺少状态记录。 也就是说如果后续处理需要前面的信息,就必须重传,这导致需要额外传递一些前面的重复请求,才能获取后续响应,然而这种效果显然太浪费资源了。
于是两种用于保持HTTP连接状态的技术就出现了,他们就是Session和Cookies。Session在服务端,也就是网站的服务器,用来保存用户的会话信息;Cookies在客户端(可以理解为浏览器端),有了Cookies,浏览器在下次访问网站时会自动附带上它发送给服务器,服务器通过识别Cookies鉴别出是哪个用户,判断是否是登录状态,然后返回对应的响应。
Cookies保存了登录的凭证,有了它,只需要在下次请求中携带Cookies发送请求 就不用重新输入用户名,密码等信息重新登录了。所以在爬虫中,一般会将登录成功后获取的Cookies放在请求头中直接请求,而不必重新模拟登录。
3.原理剖析
Session
Session指有始有终的一系列动作/消息。比如,打电话时,从拿起电话拨号到挂断电话这一过程可以称为一个Session。
而Web中,Session对象用来存储特定用户Session所需的属性和配置信息。这样,当用户在各个web网页之间跳转时,存储在Session对象的变量不会丢失,而是在整个Session中一直存在下去。当用户请求来自应用程序的web页时,如果该用户还没有Session,则Web服务器会自动创建一个Session对象。而当Session过期或被放弃的时候,服务器会终止该Session。
Cookies
Cookies指某些网站为了辨别用户身份,进行Session跟踪而存储在用户本地终端上的数据。
那么,怎么利用Cookies保持状态呢?当客户端第一次请求服务器时,服务器会返回一个请求头中 带有 Set-Cookie 的字段的相应给客户端,用来标记是哪个用户,客户端浏览器会把Cookies保存起来。当浏览器下一次再请求该网站时,浏览器会把Cookies放到请求头中一起提交给服务器,Cookies携带了SessionID信息,服务器检查该Cookies即可找到对应的Session是什么,然后再判断Session来以此辨认用户状态。
成功登陆某个网站时,服务器会告诉客户端设置哪些Cookies信息,在后续访问客户端会把Cookies发送给服务器,服务器再找到对应的Session加以判断。如果Session中某些设置登陆状态是有效的,就证明用户处于登陆状态,此时返回登陆之后才可以查看的网页内容,浏览器进行解析,用户就可以看到内容了。
反之,如果传给服务器端的Cookies是无效的,或者Session已经过期了,就不能访问页面了,现在可能受到错误的相应或者 重新登陆的页面。
所以,Cookies和Session需要配合,一个处于客户端,一个处于服务端,二者共同协作,就实现了登陆Session控制。
Cookies和Session的代码实现
下面通过代码来看看Session和Cookie来实现上面提到的原理,代码要做的事如下:
1.客户端发送一个 带有Set-Cookie 属性的请求;
2.这个请求需要由服务端用session加密算法进行加密,得到一个session_id 和 cookie 的对应字典
3.下次客户端登录时,浏览器会发送带有Cookie头部的请求的时候,用户就可以不用登陆了。
简单的Python代码如下:
首先通过一个生成随机字符串的函数生成一个session_id(在server端生成,这样做的目的是为了防止伪造用户登录)
def random_str():
seed = "sdaidhp-91e093nu23vuoiuu1c12u0,qeiwvewevrbiwclqn09hrg34r3rjwiecfhb"
s = ''
for _ in range(16):
random_index = random.randint(0, len(seed) - 2)
s += seed[random_index]
return s
然后我们需要两个字典
一个存session_id和用户信息,
另一个存http请求头部header的相关信息,
session_id = random_str()
session[session_id] = u.username #假设有个对象,通过u.username可以得到用户信息
headers['Set-Cookie'] = 'user={}'.format(session_id)
这样就可以防止有恶意用户在知道其他user的信息后,发送伪造的http请求(主要防止伪造用户,但是爬虫在知道cookie之后,还是可以发送请求的)。
之后通过add_cookie函数把cookie放入http请求头部中,就可以免登陆了。
def add_cookies(self):
cookies = self.headers.get('Cookie', '')
kvs = cookies.split('; ')
log('cookie', kvs)
for kv in kvs:
if '=' in kv:
k, v = kv.split('=')
self.cookies[k] = v
之后发送的请求中会带有Cookie字段
Cookie: user=iwcirj9ieudl3h19
以上是一个简单的cookie和Session原理实现的代码。下面来看看应用中,cookie还有那些属性。
Cookie内容
那么,Cookies里有哪些内容呢,以微博为例,在Chrome浏览器打开Application选项卡,然后选择Storage部分,最后一项为Cookies,将其点开,Name,Value就是Cookies。
解析: Name: 该Cookie的名称,一旦创建,名称不可更改。
Value
:该Cookie的值,如果值是Unicode字符,需要为字符编码,如果值是二进制数据,则需要BASE64编码。Domain
:可以访问该Cookie的域名。如果设置为12306.com,则所有以12306.com结尾的域名都可以访问该Cookie。Max age
:该Cookie失效的时间,单位为妙,常与Expires一起使用,通过它可以计算出其有效时间。Max Age如果是正数,则该Cookie在Max Age秒后失效。如果为负数,则关闭浏览器时Cookie失效。浏览器也不会以任何形式保存该Cookie。Path
:该Cookie的使用路径。如果设置为/path/,则只有路径为/path/的页面可以访问该Cookie。如果设置为/,则本域名下所有页面都可以访问该Cookie。Size
:该Cookie的大小。HTTP字段
:Cookie的httponly属性。若此属性的值为true,则只有在http头带有此Cookie信息,而不能通过document.cookie来访问此Cookie。Secure
:该Cookie是否仅被使用安全协议传输。安全协议有HTTP和SSL等,在网络上传输数据前先将数据加密。默认为false.
4.常见误区:
会话Cookie和持久Cookie
传说中 会话Cookie是把Cookie放在浏览器内存中,浏览器关闭后该Cookie失效, 持久Cookie则会保存到客户端的硬盘中,下次还可以继续时候,长久保持用户登录状态。
传说是假的,过期时间是由Cookie的Max Age或Expires决定的。 持久化Cookie是把有效时间设置得比较长,这样下次访问时 仍然携带之前的cookie,就可以直接保持登录状态。
Session误区
在谈论Session机制时,会有这样一种误解:只要关闭浏览器,Session就消失了。 这种理解是错误的。对于Session来说,除非程序通知服务器删除Session,否则服务器会一直保留。
但是在我们关闭浏览器时,浏览器不会主动在关闭之前通知服务器它将要关闭,所以服务器不会有机会知道浏览器已经关闭。之所以有这种错觉,是因为大部分Session机制使用会话Cookies来保存SessionID信息,而关闭浏览器后,Cookies消失了,再次连接服务器时,就无法找到原来的Session了。如果服务器设置的Cookies保存到硬盘上,或者用某种手段改写浏览器发出HTTP请求头,把原来的Cookies发送给服务器,则当再次打开浏览器时,仍然能够找到原来的SessionID,仍然可以保存登录状态。 由于关闭浏览器不会使Session被删除,这就需要服务器为Session设置一个失效时间,当距离客户端上一次使用Session的时间超过这个失效时间时,服务器就认为客户端停止了活动,会把Session删除以节省存储空间。