@gzm1997
2018-06-13T16:54:34.000000Z
字数 3121
阅读 1858
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 web
import datetime
from aiohttp_session import get_session
async 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"] = name
session["login"] = psw
session["time"] = str(datetime.datetime.now())
return web.json_response({
"status": True
})
return web.json_response({
"status": False
})
检查是否含有具体session字段值
from aiohttp import web
import datetime
from aiohttp_session import get_session
async 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>
```python
setup(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_storage
import aioredis
import asyncio
async 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