记录一次跨域Cookie携带问题 SameSite Secure和前后端设置 包括Nginx反向代理和Vite的前端设置

后端使用cookie记录登录信息时,登录完成后响应头会携带Set-Cookie属性,浏览器会识别Set-Cookie并在满足一些条件后将Cookie注入浏览器中。

这里的请求它如果是跨域(前端域名和后端域名不一致)的,那么Cookie将无法注入。

1 前端设置

跨域请求的情况下,浏览器默认禁止携带cookie,如果想携带cookie,需要在请求时设置withCredentials参数为true,fetch请求的设置方法为method.config.credentials = 'include'

当请求的credentials模式为include时,响应头Access-Control-Origin的值不可以是*,也就是说服务端的cors插件的origin参数,必须指定具体域名,而不能是*这种通配符

在这个设置后的Cookie注入情况

2 后端设置

前端设置完毕后,将开始设置后端,后端主要设置SameSite

SameSite允许我们声明 cookie 可以用来 first-party 或者 same-site。它会明确的给出"网站"是指哪些(哪些可以带 cookie)。网站由域名后缀和域名前部分组成,比如www.web.devweb.dev的一部分。

SameSite属性提供了三种不同的方式来管理 cookie,你可以不指定这个属性(None),或者使用StrictLax来限制 cookie 的 same-site 请求。

Strict

Strict最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。

这个规则过于严格,可能造成非常不好的用户体验。比如,当前网页有一个 GitHub 链接,用户点击跳转就不会带有 GitHub 的 Cookie,跳转过去总是未登陆状态。

Lax

Lax规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。

导航到目标网址的 GET 请求,只包括三种情况:链接,预加载请求,GET 表单。详见下表。

请求类型 示例 正常情况 Lax
链接 <a href="..."></a> 发送 Cookie 发送 Cookie
预加载 <link rel="prerender" href="..."/> 发送 Cookie 发送 Cookie
GET 表单 <form method="GET" action="..."> 发送 Cookie 发送 Cookie
POST 表单 <form method="POST" action="..."> 发送 Cookie 不发送
iframe <iframe src="..."></iframe> 发送 Cookie 不发送
AJAX $.get("...") 发送 Cookie 不发送
Image <img src="..."> 发送 Cookie 不发送

设置了StrictLax以后,基本就杜绝了 CSRF 攻击。当然,前提是用户浏览器支持 SameSite 属性。

None

这种情况下允许在 third-party 发送请求时使用 cookie

但是设置SameSiteNone时需要同时设置Secure,Cookie 只能通过 HTTPS 协议发送),否则无效。

bash 复制代码
Set-Cookie: widget_session=abc123; SameSite=None; Secure

在我们的后端并没有设置HTTPS协议,故通过设置SameSite的方式完全无效了,我们选择通过代理的方式设置。

这块设置完后的Cookie注入情况

3 代理设置

在生产环境中,我们可以通过设置前端的Nginx代理服务器,设置后端服务反向代理到前端的域名上(或者前端反向代理到后端服务器上也是一样的)这样就从根源上解决了跨域问题。

Nginx配置如下

nginx 复制代码
# 代替vite 中的代理服务 功能 反向代理后端域名到 前端
location /api {
    proxy_pass http://xx.xx.xx.xx:xx;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

这个时候,请求前端域名http://localhost:5173/api就相当于请求后端域名的http://xx.xx.xx.xx:xx/api,注意Nginx是没有重写功能的,故必须配置后端的请求路径

yaml 复制代码
servlet:
    context-path: /api

这个时候就可以正常的注入Cookie了

开发环境中的前端配置,需要通过 Vite 的代理服务器实现,具体配置如下,基本都会的

js 复制代码
server: {  
  // 指定dev sever的端口号,默认为5173  
  port: env.VITE_APP_PORT,  
  // 自动打开浏览器运行以下页面  
  // open: '/',  
  // 设置反向代理  
  proxy: {  
    // 以下示例表示:请求URL中含有"/api",则反向代理到http://localhost  
    // 例如: http://localhost:3000/api/login -> http://localhost/api/login  
    // 如果反向代理到localhost报错Error: connect ECONNREFUSED ::1:80,  
    // 则将localhost改127.0.0.1  
    '/api': {  
      target: env.VITE_API_URL,  
      changeOrigin: true,  
      // rewrite: (path) => path.replace(/^\/api/, ''),  
    },  
  },  
},
相关推荐
想用offer打牌4 小时前
MCP (Model Context Protocol) 技术理解 - 第二篇
后端·aigc·mcp
崔庆才丨静觅5 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60616 小时前
完成前端时间处理的另一块版图
前端·github·web components
KYGALYX6 小时前
服务异步通信
开发语言·后端·微服务·ruby
掘了6 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅6 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
爬山算法6 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
崔庆才丨静觅6 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment7 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端