Python 会话 SAMESITE=None 未设置

Chr*_*lle 6 python flask flask-session samesite

我在使用 chrome 和 SameSite 时遇到问题。我在 shopify iframe 中提供一个网页,当使用 Flask-login 设置会话时,chrome 告诉我:

与 URL 上的跨站点资源关联的 cookie 设置为没有该 SameSite属性。它已被阻止,因为 Chrome 现在仅在设置了SameSite=None 和 的情况下才提供具有跨站点请求的 cookie Secure

安全已设置,但我尝试以所有可能的方式设置 SameSite,但没有效果。

我试过设置

app.config['SESSION_COOKIE_SAMESITE'] = "无"

我试过了,改变了库的行为,我厌倦了在 set_cookie() 中设置属性,但似乎没有任何效果。我看到的响应没有 SameSite 属性。

(我有最新版本的flask、flask-login、flask-security 和werkzeug)

你能帮助我吗?

谢谢

Pri*_*nce 7

只是为了扩展这一点,正如您所提到的,使用flask应用程序配置,您可以设置所有内容,除非设置SESSION_COOKIE_SAMESITE=None谷歌浏览器似乎没有将值设置为“无”,然后默认为“松散”。

我解决这个问题的方法是将 cookie 添加回响应标头。首先,我必须获取 cookie 值,因为 usingrequest.cookies.get("my_cookie")似乎没有从响应中提取 cookie 值,并且始终显示为 None。

其次,使用response.set_cookie()仍然没有设置samesite=None值。我不知道为什么,因为我使用的是最新版本的flaskWerkzeug这显然应该可以解决问题,但事实并非如此。经过大量测试,我发现使用response.headers.add()作品添加Set-Cookie:标题,但我需要一种方法来提取 cookie 值以确保我可以获得相同的会话。在浏览了flask 文档和其他在线论坛之后。我发现我实际上可以打电话给SecureCookieSessionInterface班级并从那里获得签名的会话。

from flask import session
from flask.sessions import SecureCookieSessionInterface

# where `app` is your Flask Application name.
session_cookie = SecureCookieSessionInterface().get_signing_serializer(app)
Run Code Online (Sandbox Code Playgroud)

最后,我必须确保在请求建立后将相同的会话添加到响应中,而不是在每个路由上调用它,这在成熟的应用程序中似乎不可行。这是通过使用after_request装饰器完成的,该装饰器在请求后自动运行。

@app.after_request
def cookies(response):
    same_cookie = session_cookie.dumps(dict(session))
    response.headers.add("Set-Cookie", f"my_cookie={same_cookie}; Secure; HttpOnly; SameSite=None; Path=/;")
    return response
Run Code Online (Sandbox Code Playgroud)

我在 Chrome 中注意到的是,它基本上设置了一个具有相同签名值的重复 cookie。由于两者都与samesite=None响应标头中的一个相同,而另一个被 Chrome 阻止的似乎被忽略了。因此,会话通过 Flask 应用程序验证并允许访问。


JBS*_*rro 7

一个容易犯的错误(就像我所做的那样)是与None混淆"None"。请务必使用字符串而不是 python 文字,如下所示:

response.set_cookie("key", value, ..., samesite="None")
Run Code Online (Sandbox Code Playgroud)

samesite=None确实会被忽略并默认为“Lax”。


row*_*n_m 1

来自: https: //github.com/GoogleChromeLabs/samesite-examples/blob/master/python-flask.md

werkzeug假设您使用的是包含此问题修复的最新版本,您应该能够 set_cookie() 像这样使用:

from flask import Flask, make_response

app = Flask(__name__)

@app.route('/')
def hello_world():
    resp = make_response('Hello, World!');
    resp.set_cookie('same-site-cookie', 'foo', samesite='Lax');
    resp.set_cookie('cross-site-cookie', 'bar', samesite='None', secure=True);
    return resp
Run Code Online (Sandbox Code Playgroud)

否则,您仍然可以 显式设置标头

from flask import Flask, make_response

app = Flask(__name__)

@app.route('/')
def hello_world():
    resp = make_response('Hello, World!');
    resp.set_cookie('same-site-cookie', 'foo', samesite='Lax');
    # Ensure you use "add" to not overwrite existing cookie headers
    resp.headers.add('Set-Cookie','cross-site-cookie=bar; SameSite=None; Secure')
    return resp
Run Code Online (Sandbox Code Playgroud)