我有一个Flask应用程序,其会话在我的本地开发机器上运行良好。但是,当我尝试在Amazon服务器上部署它时,会话似乎不起作用。
更具体地说,未设置会话cookie。但是,我可以设置正常的cookie。我确保我有一个静态安全密钥,因为其他人已经指出这可能是一个问题。唯一的区别在于服务器的设置方式。在开发过程中,我使用
app.run()
在本地运行。部署后,我使用
app.config['SERVER_NAME'] = '12.34.56.78' # <-- insert a "real" IP
app.run(host='0.0.0.0', port=80)
我怀疑问题可能出在上面,但我并不完全确定。
会话 似乎适用于Firefox,但不适用于Chrome。
以下小型应用程序演示了该问题,底部的配置存在差异:
from flask import Flask, make_response, request, session
app = Flask(__name__)
app.secret_key = 'secretKey'
# this is to verify that cookies can be set
@app.route('/setcookie')
def set_cookie():
response = make_response('Cookie set')
response.set_cookie('cookie name', 'cookie value')
return response
@app.route('/getcookie')
def get_cookie():
if 'cookie name' in request.cookies:
return 'Cookie found. Its value is %s.' % request.cookies['cookie name']
else:
return 'Cookie not found'
# this is to check if sessions work
@app.route('/setsession')
def set_session():
session['session name'] = 'session value'
return 'Session set'
@app.route('/getsession')
def get_session():
if 'session name' in session:
return 'Session value is %s.' % session['session name']
else:
return 'Session value not found'
if __name__ == '__main__':
app.debug = True
# windows, local development
#app.run()
# Ubuntu
app.config['SERVER_NAME'] = '12.34.56.78' # <-- insert a "real" IP
app.run(host='0.0.0.0', port=80)
答案 0 :(得分:15)
这是Chrome中的“错误”,不是您的应用程序的问题。 (如果他们改变策略,它也可能会影响其他浏览器。)
RFC 2109描述了cookie的处理方式,似乎表明cookie域必须是带有TLD(.com,.net等)的FQDN,或者是完全匹配的IP地址。 original Netscape cookie spec根本没有提到IP地址。
Chrome开发人员决定比其他浏览器更严格地了解他们接受cookie域的价值。虽然在某一时间they corrected a bug阻止了IP地址上的Cookie,they have apparently backpedaled从那时起,并且不允许在非FQDN域(包括localhost)或 IP地址上使用Cookie。他们声明他们不会解决这个问题,因为他们认为这不是一个错误。
“普通”cookie正在运行的原因,但会话cookie不是您没有为“普通”cookie设置域(它是可选参数),但Flask会自动将会话cookie的域设置为SERVER_NAME
。 Chrome(和其他人)接受没有域名的Cookie并自动将其设置为响应域,因此观察到的行为差异。如果将域设置为IP地址,则可以观察到正常cookie失败。
在开发过程中,您可以通过在localhost上运行应用程序而不是将其默认为127.0.0.1来解决此问题。 Flask has a workaround如果服务器名称是localhost,则不会为会话cookie发送域。 app.run('localhost')
在生产中,没有任何真正的解决方案。您可以在域而不是IP上提供此服务,这可以解决它,但在您的环境中可能无法实现。您可以强制要求所有客户使用除Chrome之外的其他内容,这是不切实际的。或者您可以为Flask提供不同的会话接口,为已经用于localhost的IP执行相同的解决方法,尽管这可能在某种程度上不安全。
Chrome不允许使用域名为IP的Cookie,并且没有实际的解决方法。
答案 1 :(得分:1)
请注意,在@davidism发布的localhost @ https://github.com/mitsuhiko/flask/blob/master/flask/sessions.py#L211-L215的解决方法中,您可以修补Flask代码并将if rv == '.localhost': rv = None
更改为rv = None
,然后Cookie域不会设置,你的cookie将工作。
您不希望在真正的生产应用程序上执行此操作,但如果您的服务器只是某种没有敏感数据的测试/登台服务器,则可能没问题。我这样做是为了在192.168.x.x
地址上通过局域网测试应用程序,这样就可以了。
答案 2 :(得分:1)
可以使用IP在Chrome浏览器中创建会话。
我的配置文件包含以下配置:
SERVER_NAME = '192.168.0.6:5000'
SESSION_COOKIE_DOMAIN = '192.168.0.6:5000'
它允许我使用本地虚拟机,并且cookie在Chrome上完美运行,无需本地FQDN。