关于浏览器存不住cookie的问题
场景:前端域名配置了ssl证书,Nginx使用反向代理进行转发,配置如下
▼js复制代码#反向代理-START location ^~ /backend/ { proxy_pass http://127.0.0.1:8668/; # 指向后端端口 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } #反向代理-END
pc端访问域名:https://xxx.xxxxxx.xxxx 进行登录 前端发送了两个请求,分别为
- 登录请求:https://xxx.xxxxxx.xxxx/backend/api/user/login
- 获取当前登录用户信息请求:https://xxx.xxxxxx.xxxx/backend/api/user/login
第一个登录请求返回了用户信息,但第二个请求却是无权限,直接回到了登录页面
排查:经过排查发现,登录接口返回的响应头返回了Cookie
▼text复制代码set-cookie: JSESSIONID=A054FD308D135F5948AA22C8A9CA1218; Max-Age=2592000; Expires=Sun, 14 Dec 2025 06:29:53 GMT; Path=/backend/api; HttpOnly
但在获取用户信息的请求中还是无权限,且又返回了一遍Cookie
分析:后端服务在 /api/user/login 接口成功登录后,返回了一个 Set-Cookie 响应头。
在获取用户信息时前端的实际请求为https://xxx.xxxxxx.xxxx/backend/api/user/get/login
当这个请求到达 Nginx 时,location ^~ /backend/ 规则会生效,将请求转发到 http://127.0.0.1:8668/
- Nginx 收到的路径:
/backend/api/user/get/login - 转发到后端的路径:
/api/user/get/login
浏览器要发送 https://xxx.xxxxxx.xxxx/backend/api/user/get/login 请求时,会检查自己的 Cookie 仓库。
它发现有一个cookie,其 Path 是 /api
浏览器会将当前请求的路径 (/backend/api/user/get/login) 与 Cookie 的 Path (/api) 进行比较
浏览器只会在请求路径以 /api 值开头 时才发送该 Cookie
但/backend/api/user/get/login不是以/api/开头的,所以浏览器决定不发送cookie
这才导致了无权限的问题
解决:修改 Nginx 配置
不改变后端的任何代码,通过调整 Nginx 配置,让浏览器认为 /backend 目录下的所有请求都应该带上 Path=/api 的 Cookie
在反向代理的配置中,增加一个proxy_cookie_path指令,其作用为:
- 如果发现响应头中有
Set-Cookie,并且其 Path 属性值为/api,Nginx 就会将其修改为/backend/api,再发送给浏览器。 - 浏览器收到的
Set-Cookie就变成了:JSESSIONID=...; Path=/backend/api; ... - 当下次浏览器请求
/backend/api/user/get/login时,路径是以/backend/api开头的,所以它会正确地带上 Cookie
反向代理配置修改后如下:
▼text复制代码#反向代理-START location ^~ /backend/ { proxy_pass http://127.0.0.1:8668/; proxy_cookie_path /api /backend/api; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } #反向代理-END
此时再次测试登录,问题完美解决
