解决跨域下Cookie的SameSite问题(使用Nginx)

简介

  Chrome升级到80版本后,默认限制了跨域携带cookie给后端,笔者在使用iframe跨域引用页面时遇到无法传递cookie的问题,需要设置SameSite属性为None(同时需要设置Secure属性才能生效)来确保线上服务正常。但是,普通的Web框架需要升级到最新版本才支持SameSite属性,升级Web框架成本太高,且发现包括360、搜狗当前版本浏览器不兼容SameSite属性导致在加入SameSite后无法传递cookie,所以本文提出一套使用Nginx来解决SameSite问题的办法(需要使用Nginx反向代理站点)。

使用Nginx的proxy_cookie_path功能

proxy_cookie_path功能说明:

Sets a text that should be changed in the path attribute of the “Set-Cookie” header fields of a proxied server response. Suppose a proxied server returned the “Set-Cookie” header field with the attribute “path=/two/some/uri/”. The directive
proxy_cookie_path /two/ /;
will rewrite this attribute to “path=/some/uri/”.

具体配置方法(在location节点下加入,配置后重载Nginx):
  如果站点Cookie所在目录在根目录/下,设置如下:
    proxy_cookie_path / “/; secure; SameSite=None”;
  如果站点Cookie所在目录在abc目录下,设置如下:
    proxy_cookie_path /abc/ “/abc/; secure; SameSite=None”;
  如果无法确定站点Cookie目录,可使用Chrome开发者工具,监测Network下网络请求,找到Response Headers中set-cookie属性值,该值中有path属性值即为Cookie目录,也即上文要替换的/或者/abc/值。

旧浏览器不兼容SameSite问题

  笔者在通过使用proxy_cookie_path后发现一些国产浏览器比如360、搜狗浏览器不兼容SameSite属性,cookie直接无法正常传递了,通过浏览器UA判断其使用的chrome内核为较旧版本,为了兼容这些浏览器,这里需要判断UA来实施proxy_cookie_path命令,具体操作方法:
  首先,为了让nginx能判断UA中的chrome版本,笔者采用了Nginx支持的njs脚本,编译Nginx支持njs的方法:
    http://nginx.org/en/docs/http/ngx_http_js_module.html
  然后,编写njs脚本,文件可以命名为ua.js:

function getChromeVersion(r) {
	var ua = r.headersIn["user-agent"];
	if(ua){
		var flag = /Chrome\/([0-9]+)/.exec(ua);
		if(flag && flag.length > 1){
			return flag[1];
		}
	}
	return -1;
}
function getCookiePathMagicFlag(r) {
	var version = getChromeVersion(r);
	if(version != -1 && version < 79){
		return "-evil"; 
	}
	return "";
}

  这里将ua.js文件放到nginx.conf同目录下,在nginx.conf 的 http节点下加入两行:
    js_include ua.js;
    js_set $cookiePathMagicFlag getCookiePathMagicFlag;
  (这里$cookiePathMagicFlag是一个标识符,可以根据这个标识符来决定是否执行proxy_cookie_path的替换,也避免了使用nginx的if。)
  最后将上文中的proxy_cookie_path命令语句改为:
    proxy_cookie_path /$cookiePathMagicFlag “/; secure; SameSite=None”;
    或者
    proxy_cookie_path /abc/$cookiePathMagicFlag “/abc/; secure; SameSite=None”;

总结

  笔者通过以上配置,测试了包括360、搜狗、火狐、IE、chrome浏览器都可以正常传递cookie了。截至最后测试,360、搜狗最新版本(用了旧的chrome内核)依然未兼容SameSite属性。

<think>我们正在讨论的是如何在Nginx中配置SameSite属性。根据引用内容,主要使用`proxy_cookie_path`指令来设置。同时,引用[4]中还提到了针对不同浏览器版本(特别是Chrome)的兼容性处理,使用map模块来动态设置SameSite属性。 以下是步骤: 1. **基本配置(固定SameSite值)**:在Nginx的配置文件中,可以在`location`块内使用`proxy_cookie_path`指令来设置SameSite属性。例如: - 设置SameSite为Lax: ```nginx proxy_cookie_path / "/; httponly; secure; SameSite=Lax"; ``` - 设置SameSite为None(必须同时设置Secure): ```nginx proxy_cookie_path / "/; httponly; secure; SameSite=None"; ``` 2. **针对不同浏览器动态设置(高级配置)**:为了兼容那些不支持SameSite=None的旧版浏览器(如Chrome 63),可以使用Nginx的map模块根据User-Agent动态设置SameSite属性。如引用[4]所示: - 在http块中定义map,将匹配特定Chrome版本的User-Agent映射到包含SameSite=None的字符串,其他则映射到默认值(不带SameSite属性或使用Lax)。 - 然后在location块中引用这个变量。 具体配置如下: ```nginx http { # 定义map,匹配Chrome 8x, 9x, 10x, 11x等(即Chrome 80以上版本) map $http_user_agent $samesite_attr { "~*chrome/(8[0-9]|9[0-9]|10[0-9]|11[0])" '/; httponly; secure; SameSite=None'; default '/; httponly; secure; SameSite=Lax'; # 或者默认使用Lax # 注意:旧版浏览器可能不支持SameSite=None,所以这里对非匹配的浏览器使用Lax } server { location / { # ... 其他配置 proxy_cookie_path / "$samesite_attr"; # 注意:如引用[4]所述,为了解决IE问题,可能需要设置P3P头 add_header P3P 'CAO PSA OUR'; } } } ``` 注意:上述正则表达式匹配Chrome 80到110版本(根据引用[4]),对于这些版本设置SameSite=None,其他浏览器默认使用SameSite=Lax。 3. **注意事项**: - 当设置SameSite=None时,必须同时设置Secure,即cookie只能通过HTTPS传输。因此,确保你的站点启用了HTTPS。 - 对于IE浏览器,可能还需要设置P3P头(如引用[4]所示)来解决cookie问题。 4. **验证配置**: - 重新加载Nginx配置:`nginx -s reload` - 使用浏览器开发者工具查看响应头中的Set-Cookie头,确认SameSite属性是否按预期设置。 5. **其他说明**: - 如果你的应用通过Nginx反向代理,且后端应用已经设置了SameSite属性,那么Nginx的配置可能会覆盖后端的设置(取决于配置顺序)。因此,最好统一在Nginx中设置。 - 如果后端应用设置的cookie路径不是根路径(/),那么需要调整`proxy_cookie_path`的第一个参数(源路径)和第二个参数(目标路径)以匹配。 因此,回答用户的问题:在Nginx中配置SameSite属性,主要使用`proxy_cookie_path`指令,并可以通过map模块实现针对不同浏览器的动态设置。 </think>要在Nginx中配置CookieSameSite属性,可通过以下步骤实现。配置的核心是使用`proxy_cookie_path`指令,这是Nginx处理反向代理时修改Set-Cookie头部的关键指令。 ### 一、基础SameSite配置方法 在nginx.conf的`location`或`server`块中添加以下指令: ```nginx # 设置SameSite=Lax(推荐默认值) proxy_cookie_path / "/; httponly; secure; SameSite=Lax"; # 或设置SameSite=None(需站传递cookie时) proxy_cookie_path / "/; httponly; secure; SameSite=None"; ``` **参数说明**: 1. `httponly`:阻止JavaScript访问cookie 2. `secure`:强制HTTPS传输(SameSite=None时必须启用[^2][^3]) 3. `SameSite=Lax/None`:控制站行为 4. 路径`/`表示应用到所有cookie ### 二、浏览器兼容性处理 针对不同浏览器版本(如旧版Chrome不兼容SameSite),使用`map`模块动态设置: ```nginx http { # 定义浏览器版本映射 map $http_user_agent $samesite_attr { "~*chrome/(8[0-9]|9[0-9])" '/; httponly; secure; SameSite=None'; # Chrome 80+ default '/; httponly; secure; SameSite=Lax'; # 其他浏览器 } server { location / { # 应用动态配置 proxy_cookie_path / "$samesite_attr"; # IE浏览器特殊处理 add_header P3P 'CAO PSA OUR'; } } } ``` **正则解释**:`chrome/(8[0-9]|9[0-9])`匹配Chrome 80-99版本 ### 三、关键注意事项 1. **HTTPS强制要求** 设置`SameSite=None`时必须启用`secure`,否则浏览器会忽略该属性[^3] ```nginx # 错误配置(缺少secure) proxy_cookie_path / "/; SameSite=None"; # 正确配置 proxy_cookie_path / "/; secure; SameSite=None"; ``` 2. **路径匹配规则** 若后端设置的cookie有特定路径(如`/api`),需精确匹配: ```nginx # 只修改/api路径下的cookie proxy_cookie_path /api/ "/api/; secure; SameSite=None"; ``` 3. **配置验证步骤**: ```bash nginx -t # 检查配置语法 nginx -s reload # 重载配置 ``` 通过浏览器开发者工具查看响应头: ``` Set-Cookie: session=abc123; Path=/; Secure; HttpOnly; SameSite=None ``` ### 四、典型场景配置方案 | 场景 | 配置方案 | 适用条件 | |------|----------|----------| | 第三方嵌入资源 | `SameSite=None; Secure` | iframe加载资源[^3] | | 用户登录会话 | `SameSite=Lax` | 防止CSRF攻击 | | 兼容旧浏览器 | 动态`map`配置 | 支持Chrome 63+等[^4] | > **最佳实践**:除非明确需要站传递cookie(如广告跟踪),否则建议使用`SameSite=Lax`作为默认值,这是现代浏览器的安全默认设置[^1][^2]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值