Cookie 未在 cross-origin react-flask 应用程序中发送
Cookies not sending in cross-origin react-flask app
我目前正在构建一个 ReactJS(前面是“https://www.example.com”)Flask(后面是“https://server.example.com”)应用程序。 React 客户端向我的 Flask 服务器发出 GET 和 POST 请求,但首先,必须对请求进行身份验证。我使用 Flask-CORS 只接受来自“https://www.example.com”的请求。我在我的服务器上启用了“CORS_SUPPORTS_CREDENTIALS”,并且从客户端,我将获取请求设置为“凭证:'include'”。
server.py
import os
import functools
from flask import Flask, Blueprint, request, make_response
from flask_cors import CORS
from .config import Config
# Application factory pattern
def create_app():
config_object = Config()
app = Flask(__name__)
# Cross-Origin Config
CORS(app,
origins=[config_object.CORS_ALLOW_ORIGIN], # https://www.example.com
supports_credentials=config_object.CORS_SUPPORTS_CREDENTIALS # True
)
app.config.from_object(config_object)
app.register_blueprint(main)
return app
# Cookie authentication
def auth_required(view):
@functools.wraps(view)
def wrapped_view(**kwargs):
user_cookie = request.cookies.get('USER_ID_COOKIE')
session_cookie = request.cookies.get('USER_SESSION_COOKIE')
is_authenticated = verify_user_session(user_cookie, session_cookie) # T/F if this is a valid user
if is_authenticated:
# Continue to route...
return view(**kwargs)
else:
# Reject request...
response = make_response({"flash": "User not logged in."}, 403)
return response
return wrapped_view
bp = Blueprint('main', __name__)
@bp.get('/main/protected')
@auth_required
def get_protected_data():
response = make_response({"fakeData": "Do you believe in life after love?"}, 200)
return response
app = create_app()
if __name__ == "__main__":
app.run()
snippet_from_protected_client.js
const MainPage = ({ setFlashMessages }) => {
let statusOK;
let statusCode;
const isStatusOK = (res) => {
statusOK = res.ok;
statusCode = res.status;
return res.json();
}
const [data, setData] = useState(null);
useEffect(() => {
fetch(process.env.REACT_APP_SERVER + '/main/protected', { // REACT_APP_SERVER=https://server.example.com
credentials: 'include'
})
.then(isStatusOK)
.then(data => {
if (statusOK) {
setData(data.fakeData);
} else if (statusCode === 403) {
setFlashMessages(data.flash);
}
});
}, []);
return (
<main>
<div className="container-md">
<div className="row">
<div className="col-md-1"></div>
<div className="col-md-11 mt-5">
<h1 className="text-start">My Account</h1>
<p className="text-start">Just some filler text here.</p>
<p className="text-start">{ data }</p>
</div>
</div>
</div>
</main>
);
}
export default MainPage;
希望您明白我的想法——我已经缩写了很多但保留了给我带来问题的主要功能。那么现在,问题:
我的 cookies 已创建并保存在浏览器中,已使用 JS 库设置 js-cookie 如下所示:
snippet_from_login_client.js
Cookies.set('USER_ID_COOKIE', '1', { sameSite: 'none', secure: true}) // again, example
Cookies.set('USER_SESSION_COOKIE', 'ARanDomStrInGSetDURingLoGiNANDSTOrEDinTHESERVERDB', { sameSite: 'none', secure: true}) // again, example
而且我知道它们已设置好,因为我可以在开发人员工具中看到它们。但是,在对受保护路由的后续请求中,服务器接受请求(这意味着它不是 CORS 来源问题)但 @auth_required 抛出 403(如上所示)。在浏览器的开发工具中检查请求 headers 后,我可以看到请求没有与 cookie 一起发送!
请求 HEADER 来自浏览器开发者工具
* Accept: */*
* Accept-Encoding: gzip, deflate, br
* Accept-Language: en-US,en;q=0.9
* Connection: keep-alive
* Host: server.example.com
* Origin: https://www.example.com
* Referer: https://www.example.com/
* Sec-Fetch-Dest: empty
* Sec-Fetch-Mode: cors
* Sec-Fetch-Site: cross-site
* Sec-GPC: 1
* User-Agent: *DEVICE-DATA*
注意没有Cookie: --
header 尽管设置了 cookies...
为什么我的 cookie 没有发送?任何提示或线索都会非常有用。
我找到问题了!我应该将我的 cookie 域设置为“.example.com”,以便客户端将它们附加到每个请求。这是使用 js-cookie:
的方法
Cookies.set('USER_ID_COOKIE', '1', { domain: '.example.com', sameSite: 'none', secure: true}) // again, example
我不确定如何在不相关的域之间发送 cookie,但如果您的服务器和客户端的格式为 'server.domain.com' 和 'client.domain.com',那么此解决方案应该适合您。希望这对外面的人有帮助!
我目前正在构建一个 ReactJS(前面是“https://www.example.com”)Flask(后面是“https://server.example.com”)应用程序。 React 客户端向我的 Flask 服务器发出 GET 和 POST 请求,但首先,必须对请求进行身份验证。我使用 Flask-CORS 只接受来自“https://www.example.com”的请求。我在我的服务器上启用了“CORS_SUPPORTS_CREDENTIALS”,并且从客户端,我将获取请求设置为“凭证:'include'”。
server.py
import os
import functools
from flask import Flask, Blueprint, request, make_response
from flask_cors import CORS
from .config import Config
# Application factory pattern
def create_app():
config_object = Config()
app = Flask(__name__)
# Cross-Origin Config
CORS(app,
origins=[config_object.CORS_ALLOW_ORIGIN], # https://www.example.com
supports_credentials=config_object.CORS_SUPPORTS_CREDENTIALS # True
)
app.config.from_object(config_object)
app.register_blueprint(main)
return app
# Cookie authentication
def auth_required(view):
@functools.wraps(view)
def wrapped_view(**kwargs):
user_cookie = request.cookies.get('USER_ID_COOKIE')
session_cookie = request.cookies.get('USER_SESSION_COOKIE')
is_authenticated = verify_user_session(user_cookie, session_cookie) # T/F if this is a valid user
if is_authenticated:
# Continue to route...
return view(**kwargs)
else:
# Reject request...
response = make_response({"flash": "User not logged in."}, 403)
return response
return wrapped_view
bp = Blueprint('main', __name__)
@bp.get('/main/protected')
@auth_required
def get_protected_data():
response = make_response({"fakeData": "Do you believe in life after love?"}, 200)
return response
app = create_app()
if __name__ == "__main__":
app.run()
snippet_from_protected_client.js
const MainPage = ({ setFlashMessages }) => {
let statusOK;
let statusCode;
const isStatusOK = (res) => {
statusOK = res.ok;
statusCode = res.status;
return res.json();
}
const [data, setData] = useState(null);
useEffect(() => {
fetch(process.env.REACT_APP_SERVER + '/main/protected', { // REACT_APP_SERVER=https://server.example.com
credentials: 'include'
})
.then(isStatusOK)
.then(data => {
if (statusOK) {
setData(data.fakeData);
} else if (statusCode === 403) {
setFlashMessages(data.flash);
}
});
}, []);
return (
<main>
<div className="container-md">
<div className="row">
<div className="col-md-1"></div>
<div className="col-md-11 mt-5">
<h1 className="text-start">My Account</h1>
<p className="text-start">Just some filler text here.</p>
<p className="text-start">{ data }</p>
</div>
</div>
</div>
</main>
);
}
export default MainPage;
希望您明白我的想法——我已经缩写了很多但保留了给我带来问题的主要功能。那么现在,问题:
我的 cookies 已创建并保存在浏览器中,已使用 JS 库设置 js-cookie 如下所示:
snippet_from_login_client.js
Cookies.set('USER_ID_COOKIE', '1', { sameSite: 'none', secure: true}) // again, example
Cookies.set('USER_SESSION_COOKIE', 'ARanDomStrInGSetDURingLoGiNANDSTOrEDinTHESERVERDB', { sameSite: 'none', secure: true}) // again, example
而且我知道它们已设置好,因为我可以在开发人员工具中看到它们。但是,在对受保护路由的后续请求中,服务器接受请求(这意味着它不是 CORS 来源问题)但 @auth_required 抛出 403(如上所示)。在浏览器的开发工具中检查请求 headers 后,我可以看到请求没有与 cookie 一起发送!
请求 HEADER 来自浏览器开发者工具
* Accept: */*
* Accept-Encoding: gzip, deflate, br
* Accept-Language: en-US,en;q=0.9
* Connection: keep-alive
* Host: server.example.com
* Origin: https://www.example.com
* Referer: https://www.example.com/
* Sec-Fetch-Dest: empty
* Sec-Fetch-Mode: cors
* Sec-Fetch-Site: cross-site
* Sec-GPC: 1
* User-Agent: *DEVICE-DATA*
注意没有Cookie: --
header 尽管设置了 cookies...
为什么我的 cookie 没有发送?任何提示或线索都会非常有用。
我找到问题了!我应该将我的 cookie 域设置为“.example.com”,以便客户端将它们附加到每个请求。这是使用 js-cookie:
的方法Cookies.set('USER_ID_COOKIE', '1', { domain: '.example.com', sameSite: 'none', secure: true}) // again, example
我不确定如何在不相关的域之间发送 cookie,但如果您的服务器和客户端的格式为 'server.domain.com' 和 'client.domain.com',那么此解决方案应该适合您。希望这对外面的人有帮助!