将 cookies/sessions 发送到子域

Sending cookies/sessions to subdomains

正如标题所说,我正在尝试在浏览器上设置cookies/sessions。


前言:

前端:https://www.example.com

后端:https://api.example.com

前端向后端发出请求,后端创建一个 session,并在响应中将 cookie 发送回前端。


问题:

请求成功,响应显示有session,但是没有设置。报错信息如下:

This attempt to set a cookie via a Set-Cookie header was blocked because its Domain attribute was invalid with regards to the current host url.


研究:

基于 this and this,看来:

cookies can be shared is that both domains have the same main-domain

我的场景就是这种情况。主域是 example.com,子域是 www.example.comapi.example.com

此外,Mozilla official documentation 指出:

if a domain is specified, then subdomains are always included


实施

前端使用React开发,后端使用[=107开发=](烧瓶)。两者都托管在 Heroku。域名注册商使用 GoDaddy,我使用 Cloudflare 作为我的 DNS re-route 流量并设置正确的域。

示例请求如下所示:

const headers = {
   'Content-Type': 'application/json',
   'X-CSRF-Token': csrfToken 
};
...
const handleFormSubmission = async e => {
    e.preventDefault();
    await axios.post('https://backend.com/add-results', { tokenId: tokenId }, { withCredentials: true, headers: headers })
}

后端有以下设置:

...
    CORS(app, origins=["https://www.example.com"], expose_headers=["Content-Type", "X-CSRFToken"], supports_credentials=True)  
...
    app.config['SESSION_COOKIE_SECURE'] = True
    app.config['SESSION_COOKIE_HTTPONLY'] = True
    app.config['REMEMBER_COOKIE_SECURE'] = True
    app.config['REMEMBER_COOKIE_HTTPONLY'] = True
    app.config['SESSION_COOKIE_DOMAIN'] = 'example.com' 

想知道是否有人遇到过类似的问题并找到了解决方案。我从 得到了使用子域的想法,但我的实现并不顺利。


这是我得到的屏幕截图

修复实际上非常简单:

    CORS(app, origins=["https://www.example.com", "https://example.com"], expose_headers=["Content-Type", "X-CSRFToken"], supports_credentials=True)  

    app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')
    app.config['SESSION_COOKIE_SECURE'] = True
    app.config['SESSION_COOKIE_HTTPONLY'] = True
    app.config['REMEMBER_COOKIE_SECURE'] = True
    app.config['REMEMBER_COOKIE_HTTPONLY'] = True
    app.config['SESSION_COOKIE_SAMESITE'] = 'None'
    app.config['SESSION_COOKIE_DOMAIN'] = '.example.com'
    app.config['WTF_CSRF_SSL_STRICT'] = False

主要变化是:

app.config['SESSION_COOKIE_SAMESITE'] = 'None'

并且:

app.config['WTF_CSRF_SSL_STRICT'] = False

SESSION_COOKIE_SAMESITE 需要 'None' 以避免默认值 'Lax',这会阻止在浏览器上接收和设置 cookie。

WTF_CSRF_SSL_STRICT 被设置为 false,因为请求的来源和服务器需要相同(同源策略)。但是,我在我的 CORS 配置中配置了允许来源的白名单。也就是说,我认为这涵盖了这种情况。

另外,我清除了浏览器和 DNS 上的缓存。此外,我重新启动了托管前端和后端的服务器。

希望这对其他人有帮助,干杯!