我正在使用Flask在Google App Engine上构建应用。我正在使用Python示例中描述的服务器端流程实施Google+登录:https://developers.google.com/+/web/signin/server-side-flow和https://github.com/googleplus/gplus-quickstart-python/blob/master/signin.py。
两个例子都有:
credentials = oauth_flow.step2_exchange(code)
和
session['credentials'] = credentials
将凭证对象存储到Flask会话中。当我在我的Google App Engine项目上运行此代码时,出现错误:
TypeError: <oauth2client.client.OAuth2Credentials object at 0x7f6c3c953610> is not JSON serializable
正如this issue(标记为WontFix)中所讨论的,OAuth2Credentials并非由JSON可序列化设计。它有方法to_json
和from_json
,可用于存储它,例如:
session['credentials'] = credentials.to_json()
然而,在same issue:
永远不要在Cookie中存储Credentials对象,它包含应用程序
客户端ID和客户端密码。
也许我误解了Flask会话对象的工作方式,但是来自the doc:
...会话基本上可以记住从一个请求到另一个请求的信息。 Flask的做法是使用签名cookie。因此,用户可以查看会话内容,但不能修改它,除非他们知道密钥......
因此,我们不应该在会话中存储凭证对象,即使它是签名的cookie。
在我的情况下,我目前只需要重新使用访问令牌进行断开连接,因此我可以存储它。
处理这种情况的正确方法是什么?凭证是否应该存储在会话中?在这个例子中,是否应该发表评论“在这里安全地保存凭证”?
答案 0 :(得分:9)
Flask 使用使用pickle
代替JSON在会话中存储值,而Google示例代码就是为此而编写的。 Flask切换到基于JSON的格式,以减少被披露的服务器端秘密的影响(黑客可以使用pickle
而不是使用JSON来劫持您的流程。
在会话中存储 访问令牌:
session['credentials'] = credentials.access_token
如果您需要,可以使用AccessTokenCredentials
class稍后再次使用该令牌重新创建credentials
对象:
credentials = AccessTokenCredentials(session['credentials'], 'user-agent-value')
AccessTokenCredentials
对象存储仅凭据;因为它缺少客户端ID和客户端密钥,所以它不能用于刷新令牌。
用户代理价值是你可以弥补的;如果您有权访问OAuth服务器日志,它可以帮助诊断问题;与谷歌我不会指望,所以只是在这里做点什么。
答案 1 :(得分:-1)
“Flask默认使用Werkzeug提供的'安全cookie'作为会话系统。它通过挑选会话数据,压缩它和base64编码来工作。” - http://flask.pocoo.org/snippets/51/
换句话说,烧瓶真的很奇怪。您放入会话中的任何内容,都会使用服务器密钥进行加密,发送到客户端并存储在客户端中。然后,服务器在每个后续请求上接收它,并使用相同的密钥对其进行解码。这也意味着会话数据将在服务器重新启动后继续存在,因为它位于客户端。
为了改善我的应用程序,我使用了带有Couchdb的烧瓶SessionInterface - 现在客户端只知道对我的数据库检查的sessionID,其中存储了实际数据。乌拉。
检查一下,根据您使用的数据库,它有一些服务器端会话的方法 - http://flask.pocoo.org/snippets/category/sessions/