手记

基于web框架Flask的会话机制分析

一、会话技术概述

会话(Session)跟踪是Web应用程序中常用的技术,用来跟踪用户的整个会话。而Web应用程序是使用HTTP协议传输数据的,由于HTTP协议是无状态的协议,一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法单从网络连接上跟踪会话,以获知发起请求的客户端的身份。
要跟踪该会话,必须引入一种机制。于是服务器想着给每个客户端颁发一个“通行证”,同时服务器建立“客户明细表”存储通行证信息,客户端下一次携带自己的“通行证”访问服务器,服务器根据“通行证”查询“客户档案表”就可以知道来访客户端的身份了。Cookie就是存储在客户端用于跟踪“通行证”的一小段文本内容,Session则存储在服务器端检查“客户明细表”来确认客户身份。

二、Cookie和Session交互

客户端(浏览器)第一次请求服务器时,客户端的HTTP request中cookie为空,如果服务器需要记录该用户状态,就使用response向客户端颁发一个 Cookie。客户端会把Cookie保存起来。同时,服务器把客户端信息以某种形式记录在服务器上,即为Session。

当客户端再请求服务器时,客户端 的HTTP request中携带cookie数据一同提交给服务器。服务器检查该 Cookie,并从Session中查找该客户端 的状态,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。

一个cookie的设置以及发送过程分为以下四步:

三、请求和响应属性解析

cookie的请求和响应头内容如下所示:

请求头内容。客户端发送cookie给服务器时,不发送cookie的各个属性,只发送对应的名称和值。 例如: Cookie: name=value; name2=value2 ?

响应头内容。服务器发送cookie给客户端时对应为Set-Cookie,包括了对应的cookie的名称、值、以及各个属性。

例如:
Set-Cookie: lu=Rg3vHJZnehYLjVg7qi3bZjzg; Expires=Tue, 15 Jan 2013 21:47:38 GMT; Path=/; Domain=.169it.com; HttpOnly
Set-Cookie: made_write_conn=1295214458; Path=/; Domain=.169it.com
Set-Cookie: reg_fb_gate=deleted; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Path=/; Domain=.169it.com; HttpOnly

Domain:表示当前cookie所属域的名称。 Cookie是不可跨域名的。域名www.google.com颁发的Cookie不会被提交到域名www.baidu.com去。这是由Cookie的隐私安全机制决定的。隐私安全机制能够禁止网站非法获取其他网站的Cookie。正常情况下,同一个一级域名下的两个二级域名如www.helloweenvsfei.com和images.helloweenvsfei.com也不能交互使用Cookie,因为二者的域名并不严格相同。如果想所有helloweenvsfei.com名下的二级域名都可以使用该Cookie,需要设置Cookie的domain参数。

Path:表示cookie的所属路径。 path属性决定允许访问Cookie的路径(ContextPath)。例如,设置为“/”时允许所有路径使用Cookie。如果只允许/sessionWeb/下的程序使用Cookie需要设置路径。

Expire time/Max-age:表示cookie的生存期。expire值为时间值,未指定expire time时cookie只在浏览器会话期间暂时存在,当用户退出浏览器后这些值会丢失。max-age指定当前cookie存活时间,max-age用秒来设置cookie的生存期。maxAge为正数则表示该Cookie会在maxAge秒之后自动失效。浏览器会将maxAge为正数的Cookie持久化,即写到对应的Cookie文件中。无论客户关闭了浏览器还是电脑,只要还在maxAge秒之前,登录网站时该Cookie仍然有效。maxAge为负数,则表示该Cookie仅在本浏览器窗口以及本窗口打开的子窗口内有效,关闭窗口后该Cookie即失效。maxAge为负数的Cookie为临时性Cookie,不会被持久化,不会被写到Cookie文件中。Cookie信息保存在浏览器内存中,因此关闭浏览器该Cookie就消失了。Cookie默认的maxAge值为–1。如果maxAge为0,则表示删除该Cookie。Cookie机制没有提供删除Cookie的方法,因此通过设置该Cookie即时失效实现删除Cookie的效果。失效的Cookie会被浏览器从Cookie文件或者内存中删除。

secure:表示cookie的安全属性。HTTP协议不仅是无状态的,而且是不安全的。使用HTTP协议的数据不经过任何加密就直接在网络上传播,有被截获的可能。使用HTTP协议传输很机密的内容是一种隐患。如果不希望Cookie在HTTP等非安全协议中传输,可以设置Cookie的secure属性为true。浏览器只会在HTTPS和SSL等安全协议中传输此类Cookie。

httponly:表示此cookie必须用于http或https传输。这意味着,浏览器脚本,比如javascript中,是不允许访问操作此cookie的。

四、Flask中的会话机制使用

在 Flask 中使用 session 首先通过 from flask import session 导入session 模块。

Flask中操作session和操作字典是类似的,具体设置、获取、删除session的使用如下所示:

Flask视图函数处理:

@app.route('/', methods=['GET'])
def index(name = None):
    if request.method == 'GET':
        session.permanent=True  
        session['usernameY'] = 'cookie1'#设置session
        session['usernameX'] = 'cookie2'
        print(session)
        print("usernameY", session.get('usernameY'))#获取session
        print("usernameX", session.get('usernameX'))
        session.pop('usernameY')#删除指定session
        print("usernameY", session.get('usernameY'))
        print("usernameX", session.get('usernameX'))
        
        session['usernameD'] = 'cookie3'
        print("usernameD", session.get('usernameD'))
        print("usernameX", session.get('usernameX'))        
        session.clear()#删除全部session
        print("usernameD", session.get('usernameD'))
        print("usernameX", session.get('usernameX'))        
        
        resp = make_response(render_template('index.html',name=name))
        resp.set_cookie('usernameY','cookie1')
        return resp

打印结果如下:

<SecureCookieSession {'usernameY': 'cookie1', 'usernameX': 'cookie2', '_permanent':          True}>)#以特殊字典的键值对方式存储
('usernameY', 'cookie1')
('usernameX', 'cookie2')
('usernameY', None)
('usernameX', 'cookie2')
('usernameD', 'cookie3')
('usernameX', 'cookie2')
('usernameD', None)
('usernameX', None)

执行set_cookie 方法后内容会体现在响应头的Set-Cookie 属性中,其中cookie 的键是 session,值是一堆在 Cookies 的基础上进行密钥签名的字符串,由句号分割成三个部分,第一部分是 base64 加密的数据,第二部分是时间戳,第三部分是校验信息。
下一次客户端的请求头内容中包含了cookies内容,视图函数中可通过request.cookies查看。
关于设置session的有效期,默认为未设置session有效期,浏览器关闭后过期。如果设置session.permanent=True,那么会默认在31天后过期。如果不想在31天后过期,那么可以设置app.config[‘PERMANENT_SESSION_LIFETIME’] = timedelta(hour=2)在两个小时后过期。

使用HTML表单提交时,可以通过session[‘username’] = request.form[‘username’]存储用户信息。HTML的代码如下:

<form action="/signin" method=POST>
	<input class="span12" id="cont_name" name="username" type="text" placeholder="Your name" />
	<input class="span12" id="cont_password" name="password" type="password" placeholder="Your password" />
</form>
0人推荐
随时随地看视频
慕课网APP