3.1.8 Python中的cookie和安全

cookie是现在网站重要的内容,特别是当有用户登录的时候,所以有必要去学习和了解一下cookie。
因为HTTP协议是无状态的,即服务器不知道用户上一次做了什么,这严重阻碍了交互式Web应用程序的实现。cookie就是用来绕开HTTP的无状态性的“额外手段”之一。服务器可以设置或读取cookies中包含的信息,借此维护用户跟服务器会话中的状态。
cookie另一个典型的应用是,当登录一个网站时网站往往会请求用户输入用户名和密码,并且用户可以勾选“下次自动登录”。如果勾选了,那么下次访问同一网站时,用户会发现没输入用户名和密码就已经登录了。
cookie缺陷:
cookie会被附加在每个HTTP请求中,所以无形中增加了流量。
由于在HTTP请求中的cookie是明文传递的,所以安全性成问题(除非用HTTPS)。
cookie的大小限制在4KB左右,或许在某些情况下有点不够用。
对于用户来说,可以通过改变浏览器的设置来禁用cookie,也可以删除历史的cookie。
在Tornado中,也提供对cookie的读写函数,帮助我们管理和使用它。
set_cookie()get_cookie()是默认提供的两个方法,但它是明文不加密传输的。
在index.py文件的IndexHandler类的post()方法中,当用户登录,验证用户名和密码后,将用户名和密码存入cookie,内容:
#!/usr/bin/env python
# coding=utf-8
'''
Created on 2018年4月19日
'''
import tornado.web
import methods.readdb as mr

class IndexHandler(tornado.web.RequestHandler):
def get(self):
userNames = mr.selecr_columns(table="users", column="name")
first_user = userNames[0][0]
self.render("index.html",user = first_user)
def post(self):
userName = self.get_argument("username")
passWord = self.get_argument("password")
user_infos = mr.select_tab(table="users",column="*",condition="name", value="'"+userName+"'")
if user_infos:
db_wd = user_infos[0][2]
if db_wd == passWord:
self.set_cookie(userName, passWord) #设置cookie
self.write("Welcome you :"+userName)
else:
self.write("your password was not right.")
else:
self.write("There is no this user.")
上面代码中,较以前只增加了一句“self.set_cookie(userName,passWord)”,再回到登录页面,将我在登录时输入的密码以明文的方式存储在cookie里
3.1.8 Python中的cookie和安全
Tornado提供另外一种安全的方法:set_secure_cookie()get_secure_cookie(),之所以称其为安全cookie,是因为它以明文加密的方式传输。
此外,跟set_cookie()的区别还在于,set_secure_cookie()执行后的cookie保存在磁盘中,直到它过期为止。也是因为这个原因,即使关闭浏览器,在失效时间以前,cookie都一直存在。
要是用set_secure_cookie()方法设置cookie,要先在application.py文件的setting中进行如下配置:
#!/usr/bin/env python
# coding=utf-8
'''
Created on 2018年4月18日
'''
from url import url
import tornado.web
import os

settings = dict(
template_path = os.path.join(os.path.dirname(__file__),"templates") ,
static_path = os.path.join(os.path.dirname(__file__),"statics"),
cookie_secret = "bZJc2sWbQLKos6GkHn/VB9oXwQt8S0R0kRvJ5/xJ89E="
)
application = tornado.web.Application(
handlers = url,
**settings
)
其中“cookie_secret="bZJc2sWbQLKos6GkHn/VB9oXwQt8S0R0kRvJ5/xJ89E="”是为此增加的,但是,它并不是真正的加密;因为tornado会将cookie值编码为Base-64字符串,并增加一个时间戳
和一个cookie内容的HMAC签名。通常这样生成:
>>> import base64,uuid
>>> base64.b64encode(uuid.uuid4().bytes)
'OfVFe1CJTu6dRE0at1mB0Q=='
如果想要更复杂的:
>>> import base64,uuid
>>> base64.b64encode(uuid.uuid4().bytes+uuid.uuid4().bytes)
'KpVR6u7YSwyLZGhjG51m8RYrv2hk00p4oY1K4IoVHGg='
这里得到的是一个随机字符串,用它作为cookie_secret值。
然后修改index.py中设置cookie那句话,变成:
self.set_secure_cookie(userName, passWord)
再看看效果:
3.1.8 Python中的cookie和安全
麻烦了很多吧,如果要获取此cookie,用self.get_secure_cookie(userName)即可。
这样还不是最安全,还可以更安全,设置httponly和secure属性,用来防范cookie投毒:
self.set_secure_cookie(userName, passWord, httponly=True, secure=True)
用这样的方法,浏览器通过SSL连接传递cookie,能够在一定程度上防范跨站脚本攻击。