我在chrome和SameSite方面遇到问题。我正在shopify iframe中提供网页,并且在使用flask-login设置会话时,chrome会告诉我这一点:
与位于以下位置的跨站点资源关联的cookie 网址未设置
SameSite
属性。已被屏蔽,因为Chrome现在仅提供 跨站点请求的Cookie(如果已设置为SameSite=None
) 和Secure
。
设置了安全性,但是我试图以所有可能的方式设置SameSite,但没有效果。
我尝试设置
app.config ['SESSION_COOKIE_SAMESITE'] =“无”
我尝试过,更改了库的行为,我很累在set_cookie()中设置属性,但似乎没有任何效果。我看到的响应没有SameSite属性。
(我有flask的最新版本,flask-login,flask-security和werkzeug)
你能帮我吗?
谢谢
答案 0 :(得分:1)
只需对此进行扩展,就像您提到的那样,使用flask应用程序配置,就可以设置所有内容,除非设置SESSION_COOKIE_SAMESITE=None
时Google Chrome似乎没有将该值设置为“ None”,然后默认进入“宽松”状态。
我如何解决此问题是将Cookie重新添加到响应标头中。首先,我必须获取cookie值,因为使用request.cookies.get("my_cookie")
似乎没有从响应中提取cookie值,并且总是显示为None。
其次,使用response.set_cookie()
仍未设置samesite=None
的值。我不知道为什么,因为我使用的是最新版本的flask
和Werkzeug
,显然应该可以解决问题,但不能解决。经过大量测试,我发现使用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)
最后,我必须确保在建立请求之后,将相同的会话添加到响应中,而不是在成熟的应用程序中似乎不可行的每条路由上都调用它。这是通过使用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
我在Chrome中注意到的是,它基本上会设置一个具有相同签名值的重复cookie。由于两者都与响应标头中带有samesite=None
的一个相同,而另一个被Chrome阻止的元素似乎被忽略了。因此,可以使用flask应用程序验证会话并允许访问。
答案 1 :(得分:1)
一个容易犯的错误(就像我一样)是将 None
与 "None"
混淆。确保使用字符串而不是 python 文字,如下所示:
response.set_cookie("key", value, ..., samesite="None")
samesite=None
确实会被忽略并默认为“Lax”。
答案 2 :(得分:0)
来自:https://github.com/GoogleChromeLabs/samesite-examples/blob/master/python-flask.md
假设您使用的是包含the fix to this issue的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
否则,您仍然可以 set the header 明确地:
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