关于bottle WEB框架中签名cookie的一点理解
首先要理解一个概念
MAC (message authenticate code)
消息认证码(带密钥的Hash函数):密码学中,通信实体双方使用的一种验证机制,保证消息数据完整性的一种工具。
构造方法由M.Bellare提出,安全性依赖于Hash函数,故也称带密钥的Hash函数。消息认证码是基于密钥和消息摘要所获得的一个值,
可用于数据源发认证和完整性校验。
构造方法由M.Bellare提出,安全性依赖于Hash函数,故也称带密钥的Hash函数。消息认证码是基于密钥和消息摘要所获得的一个值,可用于数据源发认证和完整性校验。
签名cookie就是基于这种原理。
一般发送的数据都会做base64编码,关于base64编码可以看这个链接
blog.xiayf.cn/2016/01/24/base64-encoding/
总的来说:base64并不是用来加密的,base64是一种数据编码方式,目的让数据符合传输协议的要求,将二进制的数据转化为一种文本数据
在Python中提供了两个模块,去实现。以下是base64的基本用法
>>> import base64
>>> s='b'asdafsdafa'
SyntaxError: invalid syntax
>>> s=b'asdasdas'
>>> s_64 = base64.bencode(s) s_64 = base64.bencode(s)
AttributeError: module 'base64' has no attribute 'bencode'
>>> s_64 = base64.b64encode(s)
>>> s_64
b'YXNkYXNkYXM='
>>> base64.b64decode(s_64)
b'asdasdas'
>>>
对于mac,Python有个模块hmac基本用法如下
>>> import hmac
>>> hmac.new(b'slat')
<hmac.HMAC object at 0x0000000004110B70>
>>> hmac = hmac.new(b'slat')
>>> hmac.update(b'asdas')
>>> hmac.digest()
b'\xe8\\\xb6\x11\x9dj\rY\x06I\x1f[\x06\xeb\xeb\xf3'
>>>
文档说明
class HMAC(builtins.object)
| RFC 2104 HMAC class. Also complies with RFC 4231.
|
| This supports the API for Cryptographic Hash Functions (PEP 247).
|
| Methods defined here:
|
| __init__(self, key, msg=None, digestmod=None)
| Create a new HMAC object.
|
| key: key for the keyed hash object.
| msg: Initial input for the hash, if provided.
| digestmod: A module supporting PEP 247. *OR*
| A hashlib constructor returning a new hash object. *OR*
| A hash name suitable for hashlib.new().
| Defaults to hashlib.md5.
| Implicit default to hashlib.md5 is deprecated and will be
| removed in Python 3.6.
|
| Note: key and msg must be a bytes or bytearray objects.
|
| copy(self)
| Return a separate copy of this hashing object.
|
| An update to this copy won't affect the original object.
|
| digest(self)
| Return the hash value of this hashing object.
|
| This returns a string containing 8-bit data. The object is
| not altered in any way by this function; you can continue
| updating the object after calling this function.
|
| hexdigest(self)
| Like digest(), but returns a string of hexadecimal digits instead.
|
| update(self, msg)
| Update this hashing object with the string msg.
立即了基础,来看bottle框架设置签名cookie和获取签名cookie的值的源码.
设置签名cookie
first_bottle.py
response.set_cookie('account',username,secret='salt')
def set_cookie(self, name, value, secret=None, **options): if not self._cookies:
self._cookies = SimpleCookie() if secret:
value = touni(cookie_encode((name, value), secret))
elif not isinstance(value, basestring):
raise TypeError('Secret key missing for non-string Cookie.') if len(value) > 4096: raise ValueError('Cookie value to long.')
self._cookies[name] = value for key, value in options.items():
if key == 'max_age':
if isinstance(value, timedelta):
value = value.seconds + value.days * 24 * 3600
if key == 'expires':
if isinstance(value, (datedate, datetime)):
value = value.timetuple()
elif isinstance(value, (int, float)):
value = time.gmtime(value)
value = time.strftime("%a, %d %b %Y %H:%M:%S GMT", value)
self._cookies[name][key.replace('_', '-')] = value
self._cookie默认是None,SimpleCookie继承BaseCookie,BaseCookie继承一个字典,所以暂且认为self.cookie是一个字典,
if secret 是判断,如果设置了密钥,就执行这一步,
def tob(s, enc='utf8'):
return s.encode(enc) if isinstance(s, unicode) else bytes(s)
def touni(s, enc='utf8', err='strict'):
return s.decode(enc, err) if isinstance(s, bytes) else unicode(s)
tonat = touni if py3k else tob
touni 函数是返回str类型的字符串,这里unicode=str,unicode(s) 相当于str(s)
def cookie_encode(data, key):
''' Encode and sign a pickle-able object. Return a (byte) string '''
msg = base64.b64encode(pickle.dumps(data, -1))
sig = base64.b64encode(hmac.new(tob(key), msg).digest())
return tob('!') + sig + tob('?') + msg
pickle.dumps将数据序列化,返回的是bytes类型的字符串,然后编码为base64 sig 是先用hmac加密,
最后将msg(消息) 和sig(签名)拼接,这样一个签名cookie就设置好了,注意这里的msg是一个(name,value)包含cookie的key和value
这样一个签名cookie就设置好了
理解了签名cookie的设置,再看获得签名cookie的值就比较简单了。。
大致原理是拿到cookie的值,通过?分割出message 和sig ,再拿message和secret 进行hmac 拿到新的sig,这个新的sig与分割出来的sig比较,如果一致,表示没有被篡改,这样吧message 用base64decode
然后pickle.loads 就拿到原来的数组了。数组的[1]就是那个value,
def cookie_decode(data, key):
''' Verify and decode an encoded string. Return an object or None.'''
data = tob(data)
if cookie_is_encoded(data):
sig, msg = data.split(tob('?'), 1)if _lscmp(sig[1:], base64.b64encode(hmac.new(tob(key), msg).digest())):
return pickle.loads(base64.b64decode(msg))
因为之前setcookie时在自古穿前面加了一个感叹 号! ,所以切片sig[1:]
def _lscmp(a, b):
''' Compares two strings in a cryptographically safe way:
Runtime is not affected by length of common prefix. '''
return not sum(0 if x==y else 1 for x, y in zip(a, b)) and len(a) == len(b)
上面这个函数是逐个字符比较,如果比较的字符都相等那么就返回0,否则返回1,这样如果是两个字符串完全匹配,就都是0,调用sum() 相加肯定返回0 ,否则肯定不是1,但是必须在长度相等的条件下才可以
测试代码
>>> a='asdas'
>>> unicode(a)
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
unicode(a)
NameError: name 'unicode' is not defined
>>> b='asd'
>>> (0 if x==y else 1 for x,y in zip(a,b))
<generator object <genexpr> at 0x0000000003170200>
>>> sum((0 if x==y else 1 for x,y in zip(a,b)))
0
>>> s=zip(a,b)
>>> s
<zip object at 0x0000000003147948>
>>> for i in s:
print(i) ('a', 'a')
('s', 's')
('d', 'd')
为什么比较字符串相等不直接用 a==b?
关于bottle WEB框架中签名cookie的一点理解的更多相关文章
- Python的Django框架中的Cookie相关处理
Python的Django框架中的Cookie相关处理 浏览器的开发人员在非常早的时候就已经意识到. HTTP's 的无状态会对Web开发人员带来非常大的问题,于是(cookies)应运而生. coo ...
- 在 node.js 的 express web 框架中自动注册路由
该方法主要是动态注册自己写的 router . 注册器 router 文件名为 loader.js . var express = require('express'); var fs = requ ...
- 浅谈python web框架中的orm设计
看了一下廖雪峰的那个web框架,其实就是封装了web.py,请求使用异步并将aiomysql做为MySQL数据库提供了异步IO的驱动,前端部分则整合了jinja.其中最难的应该是orm部分了. 下面是 ...
- 蜗牛历险记(二) Web框架(中)
上篇简单介绍了框架所使用的Autofac,采用Autofac提供的Ioc管理整个Web项目中所有对象的生命周期,实现框架面向接口编程.接下来介绍框架的日志系统. 一.介绍之前 框架日志是否有存在的必要 ...
- Java Web servlet中的cookie
点击submit后: 点击查看Cookies: 在C:\Documents and Settings\Administrator\Cookies目录下面会有一个 hongten@webproj ...
- 正确理解web交互中的cookie与session
cookie存储在客户端的纯文本文件 用户请求服务器脚本 脚本设置cookie内容 并 通过http-response发送cookie内容到客户端并保存在客户端本地 客户端再次发送http请求的时候会 ...
- Bootstrap框架中的字形图标的理解
最近项目中准备使用 Bootstrap 框架,看中了Ace Admin 这套皮肤,看其代码的时候,发现使用了字形图标.下面内容来源于网络,根据自己对新知识的学习曲线重新整合了一下: 一,字形图标的定义 ...
- 对web应用中单一入口模式的理解及php实现
在我们web应用的开发中,经常会听见或看见单一入口模式,在我开始学习tp框架的时候也不理解为什么要运用一个单一入口模式,只是会使用,最近自己在搞一个小东西的时候才明白为什么在web开发中要运用单一入口 ...
- 关于css中层叠性的一点理解
关于css层叠性的一点理解 标签(空格分隔): html css 我们平时在写css的时候会遇到这样的情况 <!DOCTYPE html> <html lang="en&q ...
随机推荐
- 12.12 Daily Scrum
这周末我们会集成一下反馈活跃用户的模块. 另外,今天编译的第一次测试结束,周末这两天项目的进度会比之前加快一些. Today's Task Tomorrow's Task 丁辛 实现和菜谱相关的餐 ...
- 读书笔记(chapter4)
进程调度 4.1多任务 1.多任务系统可以划分为:非抢占式多任务和抢占式多任务: (在此模式下,由调度程序来决定什么时候停止一个进程的运行,以便其他进程能够得到执行机会,这个动作叫抢占: 时间片实际上 ...
- java.lang.Exception: No tests found matching Method tes(com.bw.test.Testrefiect) from org.junit.vintage.engine.descriptor.RunnerRequest@3bfdc050 at org.junit.internal.requests.FilterRequest.getRunner
junit 方法 没有加上注解 @Test java.lang.Exception: No tests found matching Method tes(com.bw.test.Testre ...
- Spring Cloud的Zuul的使用问题
Zuul Client 放在移动App中,Zuul Server可以做集群. Zuul Client放在jar包吗?ios怎么办? Zuul与Spring Security配合使用,与Shiro做集成 ...
- cxGrid导出Excel货币符号问题
cxGrid导出到Excel,对于Currency类型总是加上了货币符号,可以修改导出文件设置来去掉: 在cxXLSExport.pas文件中,修改: procedure TcxXLSExportPr ...
- 彻底弄懂jsonp原理及实现方法
一. 同源策略 所有支持Javascript的浏览器都会使用同源策略这个安全策略.看看百度的解释: 同源策略,它是由Netscape提出的一个著名的安全策略. 现在所有支持JavaScript 的浏览 ...
- [日常工作]GS使用安装盘修改密码后的处理
1. GS服务器端有时候需要修改 9999 的用户密码.但是修改完密码之后有几个注意事项: 一般有两个可以修改注册的地方: 使用setup里面的修改用户密码 修改完密码之后要手工注册一下数据库实例 也 ...
- 序列化与反序列化,json,pickle,xml,shelve,configparser模块
序列化与反序列化 什么是序列化?序列化就是将内存中的数据结构转换成一种中间格式存储到硬盘或者基于网络传输.反序列化就是将硬盘中或者网络中传来的一种数据格式转换成内存中数据结构. 为什么要有? 1.可以 ...
- 归并排序详解(python实现)
因为上个星期leetcode的一道题(Median of Two Sorted Arrays)所以想仔细了解一下归并排序的实现. 还是先阐述一下排序思路: 首先归并排序使用了二分法,归根到底的思想还是 ...
- 关于Spring MVC跨域
1.Sping MVC 3.X跨域 关于跨域问题,主要用的比较多的是cros跨域. 详细介绍请看https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Ac ...