问题
I am having issues with chrome and SameSite. I am serving a webpage in a shopify iframe and when setting the session using flask-login, chrome tells me this:
A cookie associated with a cross-site resource at URL was set without the
SameSite
attribute. It been blocked, as Chrome now only delivers cookies with cross-site requests if they are set withSameSite=None
andSecure
.
Secure is set, but I tried to set SameSite in all the possible way, but without effect.
I tried setting
app.config['SESSION_COOKIE_SAMESITE'] = "None"
I tried, changing the behavior of the library, I tired setting the attribute in set_cookie() but nothing seemed to work. The response I see doesn't have the SameSite attribute.
(I have the last versions of flask, flask-login, flask-security and werkzeug)
Can you help me?
Thank you
回答1:
Just to expand on this, using flask application config just as you've mentioned, you can set everything except when setting SESSION_COOKIE_SAMESITE=None
Google Chrome doesn't seem to place the value as "None", which then defaults to "Lax".
How i worked around this problem was to add the cookie back into the response header. First I had to get the cookie value because using request.cookies.get("my_cookie")
doesn't seem to extract the cookie value from the response and always appears as None.
secondly, using the response.set_cookie()
still doesn't set the samesite=None
value. I have no idea why because i'm using the latest version of flask
and Werkzeug
which apparently should fix the problem but it doesn't. After lots of testing, I found out using the response.headers.add()
works to add a Set-Cookie:
header but I needed a way to extract the cookie value to ensure I can get the same session. After looking through flask docs and other online forums. I found out that I can actually call SecureCookieSessionInterface
class and get the signed session from there.
from flask import session
from flask.sessions import SecureCookieSessionInterface
# where `app` is your Flask Application name.
session_cookie = SecureCookieSessionInterface().get_signing_serializer(app)
Lastly, i had to ensure that the same session is added to the response after the request has been established rather than calling it on every route which doesn't seem feasible within a full fledged application. This is done by using the after_request decorator which runs automatically after a 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
What I noticed in Chrome is that, it basically sets a duplicate cookie with the same signed value. Since both are identical with one having samesite=None
in the response header and the other blocked by Chrome seems to be ignored. Thus, the session is validated with the flask app and access is allowed.
回答2:
From: https://github.com/GoogleChromeLabs/samesite-examples/blob/master/python-flask.md
Assuming you're on the latest version of werkzeug
that includes the fix to this issue, you should be able to use
set_cookie()
like this:
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
Otherwise, you can still set the header explicitly:
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
来源:https://stackoverflow.com/questions/62992831/python-session-samesite-none-not-being-set