为什么会话cookie在从域服务时起作用而在使用IP时不起作用?

时间:2014-12-02 16:17:35

标签: python session cookies flask

我有一个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)

3 个答案:

答案 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。