基本内容
Nginx 做反向代理的时候,我们一般习惯添加 proxy_cookie_domain 配置,来做 cookie 的域名转换,比如
…
location /api {
proxy_pass https://b.test.com;
proxy_cookie_domain b.test.com a.test.com;
}
…
在之前的博客中我也是这么写的,但是最近在项目中发现,不配置这个属性,依然运转正常,背后冷风阵阵,我发现自己一直以来可能又理解错了这个选项,然后还在这给别人讲。。。
我们首先来看下 proxy_cookie_domain 的官方定义,
Syntax: proxy_cookie_domain off;proxy_cookie_domain domain replacement;Default: proxy_cookie_domain off;Context: http, server, locationThis directive appeared in version 1.1.15.Sets a text that should be changed in the domain 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“domain=localhost”. The directive proxy_cookie_domain localhost example.org will rewrite this attribute to“domain=example.org”.
翻译过来就是 proxy_cookie_domain 参数的作用是转换 response 的 set-cookie header 中的 domain 选项,由后端设置的域名 domain 转换成你的域名 replacement,来保证 cookie 的顺利传递并写入到当前页面中,注意 proxy_cookie_domain 负责的只是处理 response set-cookie 头中的 domain 属性,仅此而已。
但是我们知道 response 在写 set-cookie 的时候,domain 是一个可选项,并不是必填项,所以经常能看到如下这种情况
这个时候由于 set-cookie 本身就没有 domain 内容,proxy_cookie_domain 也就不没有必要了,这也是为什么在部分项目中不配置 proxy_cookie_domain 依然正常的原因。但是对于一些设置了 domain 的项目,比如这种情况下当你用 nginx 做反向代理的时候,就必须要转换一下了。
误区回溯
说到这里,我们再看看之前的错误理解:
“proxy_cookie_domain 的作用是实现前后端 cookie 域名转换,保证顺利传递”
乍一看好像也没错,但是现在想想,理解还是不够啊,因为 proxy_cookie_domain 的作用是单向的,并不是双向转换的。我们先看下 cookie 的传递过程,盗一张图先 (懒得画了。。。)
浏览器在发送请求的时候,会在 request header 中带上 cookie 项 (有内容的话),此时的 cookie 是一个字符串,一个 key=value 并用分号分割的字符串,
其中并不包含任何域名信息。这是因为浏览器在设置 cookie 选项的时候,所选取的内容都是缓存中接口域名下的。然后 request 的只要请求发送出去之后,cookie 中有关 domain 信息其实是不存在的,它只是一个普通的字符串,随便 proxy_pass 到任何位置,都会正常携带下去。因此在前端到后端的 request 的过程中,proxy_cookie_domain 是没用的
而 server 端在做响应的时候,通过 set-cookie 的 domain 属性,可以控制 cookie 的生效域名目标,做到诸如二级域名 cookie 分离等等,如果前端接收到的 set-cookie 的 domain 和当前域名不一致,或者一级域名不一致 (二级域名可以共享一级域名下的 cookie),这个 cookie 在后续的通信中就是无效的,所以这里才需要去做 domain 的转换,也就是说 response 中 set-cookie 的 domain 转换才是有意义的,这也正是 proxy_cookie_domain 的作用所在。当 reseponse 的 set-cookie 中 domain 不去设置时,cookie 顺利传入浏览器中,浏览器会自动设置这个 cookie 的生效域名为当前域名。
和这个类似的还有 proxy_cookie_path 属性,同样的该属性仅作用在修改 response set-cookie 的 path 属性,而一般情况下,用的也比较少。
唠叨两句
很多问题,有时候都是太过理所当然的以为它是怎么样的,并且生效了、达到目的了,我们就认为它是这样的了,但往往大脸就会在后面不期而至。多学习,多去关注一些底层的原理,才会发现自己理解的错误,望诸君共勉~如果错误,欢迎指出~