cookie
1、基本操作
Cookie是由服务器端生成,发送给User-Agent(一般是浏览器),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)
在后台设置cookie:
- class IndexHanlder(tornado.web.RequestHandler):
- def get(self):
- print(self.cookies) #获取http请求中携带的浏览器中的所有cookie
- print(self.get_cookie("k1")) # 获取浏览器中的cooki
- self.set_cookie("k1","v1") #为浏览器设置cookie
在前端(浏览器上使用JavaScript):
- document.cookie #获取浏览器中所有的cookie
- document.cookie.split(";") #获取浏览器中具体某一个cookie,需要先分割,再操作
- document.cookie = "k1=999" #设置cookie
由于Cookie保存在浏览器端,所以在浏览器端也可以使用JavaScript来操作Cookie:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <h1>123</h1>
- </body>
- <script>
- /*设置cookie,指定秒数过期*/
- function setCookieBySeconds(name,value,expires){
- var current_date = new Date(); //获取当前时间
- current_date.setSeconds(current_date.getSeconds() + expires);
- document.cookie = name + "= "+ value +";expires=" + current_date.toUTCString();
- }
- /*设置cookie,指定天数过期*/
- function setCookieByDays(name,value,expires){
- var current_date = new Date(); //获取当前时间
- current_date.setDate(current_date.getDate() + expires);
- document.cookie = name + "= "+ value +";expires=" + current_date.toUTCString();
- }
- </script>
- </html>
2、加密cookie(签名)
Cookie 很容易被恶意的客户端伪造。加入你想在 cookie 中保存当前登陆用户的 id 之类的信息,你需要对 cookie 作签名以防止伪造。Tornado 通过 set_secure_cookie 和 get_secure_cookie 方法直接支持了这种功能。 要使用这些方法,你需要在创建应用时提供一个密钥,名字为 cookie_secret。 你可以把它作为一个关键词参数传入应用的设置中:
- def _create_signature_v1(secret, *parts):
- hash = hmac.new(utf8(secret), digestmod=hashlib.sha1)
- for part in parts:
- hash.update(utf8(part))
- return utf8(hash.hexdigest())
- # 加密
- def _create_signature_v2(secret, s):
- hash = hmac.new(utf8(secret), digestmod=hashlib.sha256)
- hash.update(utf8(s))
- return utf8(hash.hexdigest())
- def create_signed_value(secret, name, value, version=None, clock=None,
- key_version=None):
- if version is None:
- version = DEFAULT_SIGNED_VALUE_VERSION
- if clock is None:
- clock = time.time
- timestamp = utf8(str(int(clock())))
- value = base64.b64encode(utf8(value))
- if version == 1:
- signature = _create_signature_v1(secret, name, value, timestamp)
- value = b"|".join([value, timestamp, signature])
- return value
- elif version == 2:
- # The v2 format consists of a version number and a series of
- # length-prefixed fields "%d:%s", the last of which is a
- # signature, all separated by pipes. All numbers are in
- # decimal format with no leading zeros. The signature is an
- # HMAC-SHA256 of the whole string up to that point, including
- # the final pipe.
- #
- # The fields are:
- # - format version (i.e. 2; no length prefix)
- # - key version (integer, default is 0)
- # - timestamp (integer seconds since epoch)
- # - name (not encoded; assumed to be ~alphanumeric)
- # - value (base64-encoded)
- # - signature (hex-encoded; no length prefix)
- def format_field(s):
- return utf8("%d:" % len(s)) + utf8(s)
- to_sign = b"|".join([
- b"",
- format_field(str(key_version or 0)),
- format_field(timestamp),
- format_field(name),
- format_field(value),
- b''])
- if isinstance(secret, dict):
- assert key_version is not None, 'Key version must be set when sign key dict is used'
- assert version >= 2, 'Version must be at least 2 for key version support'
- secret = secret[key_version]
- signature = _create_signature_v2(secret, to_sign)
- return to_sign + signature
- else:
- raise ValueError("Unsupported version %d" % version)
- # 解密
- def _decode_signed_value_v1(secret, name, value, max_age_days, clock):
- parts = utf8(value).split(b"|")
- if len(parts) != 3:
- return None
- signature = _create_signature_v1(secret, name, parts[0], parts[1])
- if not _time_independent_equals(parts[2], signature):
- gen_log.warning("Invalid cookie signature %r", value)
- return None
- timestamp = int(parts[1])
- if timestamp < clock() - max_age_days * 86400:
- gen_log.warning("Expired cookie %r", value)
- return None
- if timestamp > clock() + 31 * 86400:
- # _cookie_signature does not hash a delimiter between the
- # parts of the cookie, so an attacker could transfer trailing
- # digits from the payload to the timestamp without altering the
- # signature. For backwards compatibility, sanity-check timestamp
- # here instead of modifying _cookie_signature.
- gen_log.warning("Cookie timestamp in future; possible tampering %r",
- value)
- return None
- if parts[1].startswith(b""):
- gen_log.warning("Tampered cookie %r", value)
- return None
- try:
- return base64.b64decode(parts[0])
- except Exception:
- return None
- def _decode_fields_v2(value):
- def _consume_field(s):
- length, _, rest = s.partition(b':')
- n = int(length)
- field_value = rest[:n]
- # In python 3, indexing bytes returns small integers; we must
- # use a slice to get a byte string as in python 2.
- if rest[n:n + 1] != b'|':
- raise ValueError("malformed v2 signed value field")
- rest = rest[n + 1:]
- return field_value, rest
- rest = value[2:] # remove version number
- key_version, rest = _consume_field(rest)
- timestamp, rest = _consume_field(rest)
- name_field, rest = _consume_field(rest)
- value_field, passed_sig = _consume_field(rest)
- return int(key_version), timestamp, name_field, value_field, passed_sig
- def _decode_signed_value_v2(secret, name, value, max_age_days, clock):
- try:
- key_version, timestamp, name_field, value_field, passed_sig = _decode_fields_v2(value)
- except ValueError:
- return None
- signed_string = value[:-len(passed_sig)]
- if isinstance(secret, dict):
- try:
- secret = secret[key_version]
- except KeyError:
- return None
- expected_sig = _create_signature_v2(secret, signed_string)
- if not _time_independent_equals(passed_sig, expected_sig):
- return None
- if name_field != utf8(name):
- return None
- timestamp = int(timestamp)
- if timestamp < clock() - max_age_days * 86400:
- # The signature has expired.
- return None
- try:
- return base64.b64decode(value_field)
- except Exception:
- return None
- def get_signature_key_version(value):
- value = utf8(value)
- version = _get_version(value)
- if version < 2:
- return None
- try:
- key_version, _, _, _, _ = _decode_fields_v2(value)
- except ValueError:
- return None
- return key_version
五、Session(依赖于cookie)
由于cookie中需要保存客户的很多信息,而且如果信息很多的话,服务端与客户端交互的时候也浪费流量,所以我们需要用很少的一段字符串来保存很多的信息,这就是我们所要引进的session。
cookie 和session 的区别:
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗 考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能 考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
5、所以个人建议: 将登陆信息等重要信息存放为SESSION 其他信息如果需要保留,可以放在COOKIE中
(1)利用session实现用户验证
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- import tornado.web
- import tornado.ioloop
- import hashlib
- import time
- li = {}
- class IndexHanlder(tornado.web.RequestHandler):
- def get(self):
- obj = hashlib.md5()
- obj.update(bytes(str(time.time()),encoding="utf-8"))
- random_str = obj.hexdigest()
- li[random_str]={}
- li[random_str]["k1"]=123
- li[random_str]["k2"]=456
- li[random_str]["is_login"]=True
- self.set_cookie("qqqqqq",random_str)
- self.write("成功设置cookie")
- def post(self, *args, **kwargs):
- pass
- class ManagerHanlder(tornado.web.RequestHandler):
- def get(self):
- random_str = self.get_cookie("qqqqqq",None)
- current_user_info = li.get(random_str,None)
- if not current_user_info:
- self.redirect("/index")
- else:
- if li[random_str]["is_login"]:
- self.write("欢迎")
- else:
- self.redirect("/index")
- def post(self, *args, **kwargs):
- pass
- settings={
- "template_path":"tpl",
- "static_path":"st",
- "cookie_secret":"123"
- }
- class IndeHanlder(tornado.web.RequestHandler):
- def get(self):
- self.render("1.html")
- application = tornado.web.Application([
- (r"/index", IndexHanlder),
- (r"/manager", ManagerHanlder),
- ],**settings)
- if __name__ == "__main__":
- application.listen(8888)
- tornado.ioloop.IOLoop.instance().start()
(2)利用session验证用户精简版
- #!/usr/bin/env/python
- # -*- coding:utf-8 -*-
- import tornado.web
- container = {}
- # container = {
- # # "第一个人的随机字符串":{},
- # # "第一个人的随机字符串":{'k1': 111, 'parents': '你'},
- # }
- class Session:
- def __init__(self, handler):
- self.handler = handler
- self.random_str = None
- def __genarate_random_str(self):
- import hashlib
- import time
- obj = hashlib.md5()
- obj.update(bytes(str(time.time()), encoding='utf-8'))
- random_str = obj.hexdigest()
- return random_str
- def __setitem__(self, key, value):
- # 在container中加入随机字符串
- # 定义专属于自己的数据
- # 在客户端中写入随机字符串
- # 判断,请求的用户是否已有随机字符串
- if not self.random_str:
- random_str = self.handler.get_cookie('__kakaka__')
- if not random_str:
- random_str = self.__genarate_random_str()
- container[random_str] = {}
- else:
- # 客户端有随机字符串
- if random_str in container.keys():
- pass
- else:
- random_str = self.__genarate_random_str()
- container[random_str] = {}
- self.random_str = random_str
- container[self.random_str][key] = value
- self.handler.set_cookie("__kakaka__", self.random_str)
- def __getitem__(self, key):
- # 获取客户端的随机字符串
- # 从container中获取专属于我的数据
- # 专属信息【key】
- random_str = self.handler.get_cookie("__kakaka__")
- if not random_str:
- return None
- # 客户端有随机字符串
- user_info_dict = container.get(random_str,None)
- if not user_info_dict:
- return None
- value = user_info_dict.get(key, None)
- return value
- class BaseHandler(tornado.web.RequestHandler):
- def initialize(self):
- self.session = Session(self)
- class IndexHandler(BaseHandler):
- def get(self):
- if self.get_argument('u',None) in ['alex','eric']:
- self.session['is_login'] = True
- self.session['name'] =self.get_argument('u',None)
- print(container)
- else:
- self.write('请你先登录')
- class MangerHandler(BaseHandler):
- def get(self):
- val = self.session['is_login']
- if val:
- self.write(self.session['name'])
- else:
- self.write('登录失败')
- class LoginHandler(BaseHandler):
- def get(self,*args,**kwargs):
- self.render('login.html',status="")
- def post(self, *args, **kwargs):
- user = self.get_argument('user',None)
- pwd = self.get_argument('pwd',None)
- code = self.get_argument('code',None)
- check_code = self.session['CheckCode']
- if code.upper() == check_code.upper():
- self.write('验证码正确')
- else:
- self.render('login.html',status ='验证码错误')
- class CheckCodeHandler(BaseHandler):
- def get(self,*args,**kwargs):
- import io
- import check_code
- mstream = io.BytesIO()
- img, code = check_code.create_validate_code()
- img.save(mstream,'GIF')
- self.session['CheckCode']=code
- self.write(mstream.getvalue())
- class CsrfHandler(BaseHandler):
- def get(self,*args,**kwargs):
- self.render("csrf.html")
- def post(self, *args, **kwargs):
- self.write("hahahahaah")
- settings = {
- 'template_path':'views',
- 'static_path':'static',
- "xsrf_cookies":True
- }
- application = tornado.web.Application([
- (r'/index',IndexHandler),
- (r'/manger',MangerHandler),
- (r'/login',LoginHandler),
- (r'/check_code',CheckCodeHandler),
- (r'/csrf',CsrfHandler),
- ],**settings)
- if __name__ == "__main__":
- application.listen(8888)
- tornado.ioloop.IOLoop.instance().start()
cookie的更多相关文章
- 超大 Cookie 拒绝服务攻击
有没有想过,如果网站的 Cookie 特别多特别大,会发生什么情况? 不多说,马上来试验一下: for (i = 0; i < 20; i++) document.cookie = i + '= ...
- IE10、IE11 User-Agent 导致的 ASP.Net 网站无法写入Cookie 问题
你是否遇到过当使用一个涉及到Cookie操作的网站或者管理系统时,IE 6.7.8.9下都跑的好好的,唯独到了IE10.11这些高版本浏览器就不行了?好吧,这个问题码农连续2天内遇到了2次.那么,我们 ...
- 解决cookie跨域访问
一.前言 随着项目模块越来越多,很多模块现在都是独立部署.模块之间的交流有时可能会通过cookie来完成.比如说门户和应用,分别部署在不同的机器或者web容器中,假如用户登陆之后会在浏览器客户端写入c ...
- jquery插件的用法之cookie 插件
一.使用cookie 插件 插件官方网站下载地址:http://plugins.jquery.com/cookie/ cookie 插件的用法比较简单,直接粘贴下面代码示例: //生成一个cookie ...
- 一个诡异的COOKIE问题
今天下午,发现本地的测试环境突然跑不动了,thinkphp直接跑到异常页面,按照正常的排错思路,直接看thinkphp的log 有一条 [ error ] [2]setcookie() expects ...
- [转载]Cookie/Session的机制与安全
Cookie和Session是为了在无状态的HTTP协议之上维护会话状态,使得服务器可以知道当前是和哪个客户在打交道.本文来详细讨论Cookie和Session的实现机制,以及其中涉及的安全问题. 因 ...
- jquery.cookie的使用
今天想到了要为自己的影像日记增加赞的功能,并且需要用到cookie. 记得原生的js操作cookie也不是很麻烦的,但似乎jquery更简单,不过相比原生js,需要额外引入2个文件,似乎又不是很好,但 ...
- 跨域问题,前端主动向后台发送cookie
跨域是什么? 从一个域名的网页访问另一个域名的资源,就会出现跨域.只要协议.端口.域名有一个不同就会出现跨域 例如: 1.协议不同 http://www.baidu.com:80 和 https:/ ...
- 【流量劫持】沉默中的狂怒 —— Cookie 大喷发
精简版:http://www.cnblogs.com/index-html/p/mitm-cookie-crack.html 前言 上一篇文章 讲解了如何借助前端技术,打造一个比 SSLStrip 更 ...
- 好好了解一下Cookie
Cookie的诞生 由于HTTP协议是无状态的,而服务器端的业务必须是要有状态的.Cookie诞生的最初目的是为了存储web中的状态信息,以方便服务器端使用.比如判断用户是否是第一次访问网站.目前最新 ...
随机推荐
- C++ STL简述
前言 最近要找工作,免不得要有一番笔试,今年好像突然就都流行在线笔试了,真是搞的我一塌糊涂.有的公司呢,不支持Python,Java我也不会,C有些数据结构又有些复杂,所以是时候把STL再看一遍了-不 ...
- Java三大框架之——Hibernate
什么是Hibernate? Hibernate是基于ORM(O:对象,R:关系,M:映射)映射的持久层框架,是一个封装JDBC的轻量级框架,主要实现了对数据库的CUPD操作. 注:CRUD是指在做计算 ...
- JavaScript闭包(Closure)
JavaScript闭包(Closure) 本文收集了多本书里对JavaScript闭包(Closure)的解释,或许会对理解闭包有一定帮助. <你不知道的JavsScript> Java ...
- CentOS7安装NodeJS6.9
1.下载 wget https://nodejs.org/dist/v6.9.2/node-v6.9.2-linux-x64.tar.xz 2.解压 tar -xJf node-v6.9.2-linu ...
- NSURLConnection实现文件上传和AFNetworking实现文件上传
请求的步骤分为4步 1.创建请求 2.设置请求头(告诉服务器这是一个文件上传的请求) 3.设置请求体 4.发送请求 NSURLConnection实现文件上传 // 1.创建请求 NSURL *url ...
- text-overflow
text-overflow:clip | ellipsis 默认值:clip 适用于:所有元素 clip: 当对象内文本溢出时不显示省略标记(...),而是将溢出的部分裁切掉. ellipsis: 当 ...
- VmWare平台Windows Server 2012 无响应宕机
我们生产服务器都部署在VMware ESXi 5.5平台上,最近大半年的时间,偶尔就会出现操作系统为Windows Servre 2012的服务器出现没有任何响应(unresponsive)的情况,出 ...
- currentStyle与getComputedStyle应用
getComputedStyle获取的是计算机(浏览器)计算后的样式,但是不兼容IE6.7.8(主要用于非IE浏览器) currentStyle方法兼容IE6.7.8,但是不兼容标准浏览器(主要用于I ...
- 高级数据过滤(like)
单字符过滤 '_' select * from T_Employee where FName like '_erry' 多字符过滤 '%' select * from T_Employee wher ...
- JAVA NIO Socket通道
DatagramChannel和SocketChannel都实现定义读写功能,ServerSocketChannel不实现,只负责监听传入的连接,并建立新的SocketChannel,本身不传输数 ...