@gzm1997
2018-06-13T08:54:34.000000Z
字数 3121
阅读 2125
aiohttp session
服务端和客户端之间的联系一般是根据http协议来进行的 但是http协议是无状态的 无状态会有状态的概念大概如下
有状态
无状态
因此服务端和客户端之间需要一种机制来记录用户的状态 这种机制在客户端那边是cookies 在服务端那边是session
cookies可以存储在磁盘 内存里面 session可以存储在内存 缓存 redis甚至磁盘中
flask框架具有内置的session机制 我以前用起来觉得非常方便以至于我觉得这个不重要 aiohttp不具有内置的session机制 但是具有第三方模块支持 aiohttp_session
安装这个第三方模块真的挺费事 因为依赖模块实在太多了 而且aiohttp_session是可以依赖redis作为缓存的 还需要安装redis和一些相关模块 下面的开始的实例我没有使用redis作为存储位置 而是使用了EncryptedCookieStorage 后面附加了使用redis存储session的例子
dependencies
安装模块
pip3 install aiohttp_sessionsss
上面的安装问题真的太多 谷歌好几次才解决
所有仓库是使用名为AIOHTTP_COOKIE_SESSION的对象来进行存储数据的
可以使用的仓库有
使用上跟flask的session大同小异 但是需要在init app阶段将session安装到app上 设定一个32位bytes作为加密密钥 跟flask session的secret key类似
session是一个dict like的对象
设定session
from aiohttp import webimport datetimefrom aiohttp_session import get_sessionasync def login(request):engine = await aio_engine.init_engine()data = await request.json()print("data", data)if "name" not in data or "psw" not in data:return web.json_response({"status": False})name = data["name"]psw = data["psw"]verify = await keeper.verify(engine, name = name, psw = psw)if verify:session = await get_session(request)session["ooad"] = namesession["login"] = pswsession["time"] = str(datetime.datetime.now())return web.json_response({"status": True})return web.json_response({"status": False})
检查是否含有具体session字段值
from aiohttp import webimport datetimefrom aiohttp_session import get_sessionasync def need_cookies_page(request):engine = await aio_engine.init_engine()session = await get_session(request)if "ooad" not in session or "login" not in session or "time" not in session:return web.json_response({"status": False})name = session["ooad"]psw = session["login"]r = await keeper.verify(engine, name = name, psw = psw)if r:return web.json_response({"status": True})return web.json_response({"status": False})````setup app<div class="md-section-divider"></div>```pythonsetup(app, EncryptedCookieStorage(b'Thirty two length bytes key.'))
login result
login cookies
cookies check

这里有个问题 就是aiohttp本事内置一个asyncio event loop执行所有跟app相关的协程了 但是当我们使用redis作为仓库进行存储session的时候需要使用到aioredis进行支持 但是这个也是异步io连接模块 因此我们初始化redis pool的时候也需要一个event loop进行运行这个初始化的协程 一旦这个event loop跟web.run_app混在一起就会报错 event loop is already run
正确的做法是分开 并且在执行redis pool连接的event loop run_until_complete处获取返回值 得到需要的storage
from aiohttp_session import setup, redis_storageimport aioredisimport asyncioasync def get_storage():redis = await aioredis.create_pool(("localhost", 6379))return redis_storage.RedisStorage(redis)def setup_session_support(app):storage = asyncio.get_event_loop().run_until_complete(get_storage())setup(app, storage)return app
app = session_redis.setup_session_support(app)
效果
可以看到生成的cookies值确实存在了redis中
postman中获取的cookies
redis中也存有一样的cookies
