烧瓶会话不保留数据

时间:2018-10-10 06:01:13

标签: python session flask

我有一个Javascript应用程序和一个Flask应用程序。当用户将数据从Js发送到Flask时,我将其存储在session上,并且在特定的路由上可以正常工作:

@app.route(...)
def user(...):
    session['name'] = name

    print(session['name']) # Works !

但是当我从另一个方法/路由获取会话中的值时,会话为空:

@app.route(...)
def current():
    print(session.keys(), session.values) # Empty !

我已经安装了Flask Session并将配置设置为:

'SECRET_KEY': b'...',

'SESSION_TYPE': 'filesystem', # Memcache, null and redis

'SESSION_PERMANENT': False, # True

然后启动Flask应用程序,它不起作用。在向会话添加一些新值后仍然无法正常工作,我还尝试设置session.modified = True

我在Stack Over Flow,Reddit等上阅读了很多线程;没有任何效果。请提示?

3 个答案:

答案 0 :(得分:2)

我在 html 中使用经典的 post 请求时遇到了同样的问题。会话仍然在之前的路由中存储值,在我发布请求后会自行清空。

我使用以下方法解决了这个问题:

app.config.update(SESSION_COOKIE_SAMESITE="None", SESSION_COOKIE_SECURE=True)

如果其他人也面临同样的问题,我将与您分享。

答案 1 :(得分:1)

TL; DR,在后端启用CORS和凭据支持,并在发出请求时在前端代码中使用凭据。

我最近遇到了一个类似的问题,当时我在单独的应用程序中开发前端和后端。我注意到,每次我从前端客户端发出请求时,都会为每个请求创建一个新会话,这将使后端的会话存储迅速膨胀,并且即使不是不可能,也会使用户难以跟踪。

我假设您的Javascript应用程序和Flask应用程序分别运行(即javascript不在Flask应用程序提供的模板上,因此js请求来自不同的来源)。

假设我们有一个简单的应用程序,它在端口5000上运行了Flask-Session:

from flask import Flask, session
from flask_session import Session

app = Flask(__name__)

SECRET_KEY = "changeme"
SESSION_TYPE = 'filesystem'
app.config.from_object(__name__)
Session(app)

@app.route('/foo')
def foo():
    return session.sid


@app.route('/bar')
def bar():
    return session.sid

现在,如果在浏览器上导航到任一路由(例如http://localhost:5000/foo)时运行应用程序,我们将获得相同的会话ID。如果打开另一个选项卡,打开开发人员工具,然后在控制台中发出以下命令,则会出现cors错误:

// Using fetch, you can use jquery or axios    
fetch("http://localhost:5000/foo").then(response => {
    return response.text()
}).then(data => {
    console.log(data)
})

您可以通过安装Flask-CORS并将应用包装到CORS类中来轻松解决此问题:

from flask import Flask, session
from flask_session import Session
from flask_cors import CORS

app = Flask(__name__)

SECRET_KEY = "changeme"
SESSION_TYPE = 'filesystem'
app.config.from_object(__name__)
Session(app)
CORS(app)

@app.route('/foo')
def foo():
    return session.sid


@app.route('/bar')
def bar():
    return session.sid

现在,如果您运行上面的javascript fetch函数,则即使调用相同的路由,每次调用请求时,它也会打印出不同的会话ID。这是因为Flask无法跟踪会话,除非您从相同的来源发出请求,或者除非您提供了一些方法让flask识别会话。您可以通过允许传递凭据来从JS中做到这一点:

fetch("http://localhost:5000/foo",
    { credentials: 'include' }).then(response => {
        return response.text()
}).then(data => {
    console.log(data)
})

但是,您将收到另一个有关Access-Control-Allow-Credentials的CORS错误。您可以通过导入cross_origin装饰器,将路线包装在装饰器中,并将supports_credentials = True传递给装饰器,在Flask应用中解决此问题。烧瓶代码如下所示:

from flask import Flask, session
from flask_session import Session
from flask_cors import CORS, cross_origin

app = Flask(__name__)

SECRET_KEY = "changeme"
SESSION_TYPE = 'filesystem'
app.config.from_object(__name__)
Session(app)
CORS(app)

@app.route('/foo')
@cross_origin(supports_credentials=True)
def foo():
    return session.sid


@app.route('/bar')
@cross_origin(supports_credentials=True)
def bar():
    return session.sid

现在flask可以跟踪请求者的会话(在本例中为运行Javascript应用的浏览器)。

答案 2 :(得分:-1)

从JS应用程序发出第一个请求后,Flask应用程序将返回一个会话cookie。存储会话ID(在JS应用上),并在后续请求中使用它。这样可以确保两个(或多个)请求处于同一会话中。没有这个,每个请求将有不同的会话。