我在Flask中构建我的应用程序,并且我在使用Cookie时遇到了一些非常奇怪的行为。
我的应用程序由多个节点提供服务,因此我必须构建自己的会话管理器以与Dynamo Db集成。
这非常简单:
当用户登录时,如果他们成功进行身份验证,我创建一个UUID4作为他们的会话ID,将此ID与一些数据一起存储在Dynamo中,然后我将cookie发送给用户{{1 } field设置为生成的UUID。
session_id
为了完整起见,这里是实际创建会话的if authenticate(user): #validates user credentials
permissions = get_permissions(user) #gets user permissions
if permissions:
#creates session in dynamo
s = create_session(user['id'], permissions)
if s:
response = make_response(redirect(url_for('index')))
response.set_cookie('session_id', s['SessionId'])
return response
else:
return 'Internal Error', 500
else:
return 'Internal Error', 500
else:
return redirect(url_for('login', q='invalid'))
函数的代码:
create_session
然而,这是我遇到的行为:
- 我在一个浏览器中以用户1身份登录,我成功通过身份验证,然后将其带到欢迎页面,在那里我可以看到我以用户1登录
- 然后我在另一个浏览器中以用户2身份登录,成功进行身份验证,然后我被带到欢迎页面但是我可以看到我以用户1登录
- 然后我查看浏览器的网络活动资源管理器,我可以看到,在用户2的情况下,服务器回复了2个SET-COOKIE标头。第一个是cookie用户2应该已经获得,但第二个是cookie,只应该发送用户1。
从用户2的浏览器获取的响应标头如下所示:
def create_session(user_id, permissions):
id = str(uuid.uuid4())
data = {
'SessionId': id,
'data': {
'user_id': user_id,
'datetime': str(datetime.utcnow()),
'permissions': permissions
}
}
try:
s = sessions.put_item(data=data)
except:
pass
return data if s else False
e67e56cd-cd75-4671-8003-445152a9b850是session_id用户2应该接收但是它显然被第二个标头覆盖 - 我不知道第二个SET-COOKIE标头来自哪里。因为......如果我这样做:
Content-Length:209
Content-Type:text/html; charset=utf-8
Date:Sun, 13 Sep 2015 13:16:44 GMT
Location:http://dev.remedize.com:8080/
Server:Werkzeug/0.10.4 Python/2.7.9
Set-Cookie:session_id=e67e56cd-cd75-4671-8003-445152a9b850; Path=/
Set-Cookie:session_id=e06a9131-7a2d-4bd0-a7dc-6cd1964633dd; Path=/
同样的请求在我的控制台中显示了这些标题:
@app.after_request
def after_request(response):
print response.headers
第二个SET-COOKIE似乎没有出现在输出上。
请注意,每次都不会发生这种情况。
然后我认为这是我的网络服务器的一个问题,但后来我意识到它发生在我的开发烧瓶服务器和我的生产nginx服务器上。
由于这对我来说完全没有意义,我在下面的代码中做了很多调试,我可以绝对肯定地说,每次Content-Type: text/html; charset=utf-8
Content-Length: 209
Location: /
Set-Cookie: session_id=e67e56cd-cd75-4671-8003-445152a9b850; Path=/
肯定会返回一个新的会话,一个新的UUID。正如您所看到的,没有代码可以从Dynamo中提取任何其他会话。
感兴趣的是,我尝试更换:
create_session
带
response = make_response(redirect(url_for('index')))
我自己无法再重新创建这种行为,但我的用户仍然注意到这种情况的随机发生。查看我的日志,我可以看到他们登录时生成了正确且唯一的session_ids。
如果有人有任何想法我会出错,我将永远感激不尽。我是以错误的方式使用cookies吗?我傻了吗?任何建议都会很棒。感谢!!!