验证跨域 cookie 的坑

坑点 1:伪跨域测试 (localhost 骗局) 问题: 前后端都用 localhost,虽然端口不同 (比如 3000 和 4000),前后端都是同站点,都是 localhostsameSite: 'strict' 在这种场景不生效,因为他只限制,就是如果是不同站点的话,就不发 cookie,但是现在明显是同站点,都是 localhost,cookie 照样发,测不出跨域问题!

解决: 狠心让前后端"分手"!前端用 http://localhost:3000,后端用 http://127.0.0.1:4000,现在前后端既跨域,又是不同站点。

坑点 2:Cookie 设置被浏览器无视 (secure + sameSite 强制 CP)

问题: 后端设置了 sameSite: 'none'(允许跨域带 Cookie),但必须同时加 secure: true(只允许 HTTPS)。不加这个,浏览器直接扔了你的 Cookie!

测试环境: 谷歌浏览器允许在设置了 secure: true 的情况下,测试环境使用 http 依旧可以发送 cookie(但是仅限当前会话,浏览器一刷新 cookie 就丢了)。

解决: 后端发 Cookie 必须锁死这对组合

arduino 复制代码
res.cookie('名字', '值', {
  sameSite: 'none',
  secure: true,   // 这俩必须同时出现!
  // ...其他配置
});

坑点 3:credentials: 'include'

credentials: 'include' 的作用:

  1. 浏览器携带相关 Cookie 给后端。
  2. 浏览器保存后端送来的 Cookie,也就是说你不设置这个东西,后端给的 Cookie 前端不会保存的。

解决:

arduino 复制代码
await fetch(后端地址, {
  method: 'GET', // 或其他
  credentials: 'include' // 关键!意思是:我要存/带 Cookie!
});

坑点 4:Access-Control-Allow-Credentials

Access-Control-Allow-Credentials: true 的作用是:

允许浏览器携带 cookie,这个属性主要是告诉浏览器,你能不能带东西过来,如果我不允许,你还带,浏览器自己就会报 cors 错误。

解决:

arduino 复制代码
// 你的手动 CORS 中间件里:
res.setHeader('Access-Control-Allow-Credentials', 'true'); // 必须加这行!

如果不设置这个属性:

你前端带东西过去,后端不允许你前端带东西,那前端就报错了。

最后给出验证代码

xml 复制代码
<!-- frontend/index.html -->
<!DOCTYPE html>
<html lang="">
<meta charset="utf-8"></meta>
<head>
  <title>跨域Cookie演示</title>
</head>
<body>
<h1>跨域Cookie设置演示</h1>
<button id="requestBtn">发送跨域请求</button>
<script>
  document.getElementById('requestBtn').addEventListener('click', async () => {
    try {
      const backendUrl = 'http://127.0.0.1:4000/api/cookie'
​
      await fetch(`${backendUrl}/set`, {
        method: 'GET',
        credentials: 'include' // 保存后端送来的 cookie
      })
​
      await fetch(`${backendUrl}/get`, {
        method: 'GET',
        credentials: 'include' // 携带已有的 cookie 发送给后端
      })
​
    } catch (error) {
      console.error('发生错误:', error)
    }
  })
</script>
</body>
</html>
javascript 复制代码
const express = require('express')
const cookieParser = require('cookie-parser')
​
const app = express()
const BACKEND_PORT = 4000
​
// 关键中间件
app.use(cookieParser())
app.use(express.json())
​
// 手动CORS中间件 (替换cors库)
app.use((req, res, next) => {
  // 1. 允许任意源访问
  const origin = req.headers.origin
  if (origin) {
    res.setHeader('Access-Control-Allow-Origin', origin)
  }
​
  // 1.允许前端保存 cookie 2.允许前端传递 cookie
  res.setHeader('Access-Control-Allow-Credentials', 'true')
​
  next()
})
​
// Route 1: 设置Cookie
app.get('/api/cookie/set', (req, res) => {
  // 关键Cookie设置 (注意属性)
  res.cookie('custom_cookie', 'super_secret_value', {
    secure: true,     // 在 https 请求才会携带 cookie(sameSite: 'none',时 secure: true 要同时成立)
    sameSite: 'none',  // 必须:允许跨域访问
    path: '/',         // 整个网站可用
    maxAge: 36000000    // 过期时间
  })
​
  res.send('Cookie已设置!检查浏览器控制台的Network标签')
})
​
// Route 2: 检查Cookie是否被发回
app.get('/api/cookie/get', (req, res) => {
  console.log(req.cookies)
​
  res.send(req.cookies)
})
​
app.listen(BACKEND_PORT, () => {
  console.log(`
╔═════════════════════════════════════════╗
║  后端服务运行中                          ║
║  地址: http://localhost:${BACKEND_PORT} ║
╚═════════════════════════════════════════╝
  `)
})

总之,因为浏览器默认跨域是不会保存 cookie 的,总之为了跨域 cookie 不出问题,前端就要 credentials: 'include',后端就要 res.setHeader('Access-Control-Allow-Credentials', 'true')

当然这都是我在本地测试的环境,鬼知道谷歌浏览器的本地测试,还有其他不同浏览器有没有不同的差异,或者上线实际的生产环境,https环境,会不会有什么其他的问题,这都是有待测试的,有其他兄弟测试过,也可以跟我讲一讲。

相关推荐
qq_459131702 分钟前
前端面试问题
前端
拾光拾趣录28 分钟前
从“祖传”构造函数到 `class`
前端·javascript
wmm_会飞的@鱼32 分钟前
FlexSim-汽车零部件仓库布局优化与仿真
服务器·前端·网络·数据库·数学建模·汽车
yvvvy34 分钟前
从“按钮都不会点”到“能撸大厂 UI”:我用 react-vant 踢开组件库的大门!
前端·javascript
安然dn35 分钟前
Cropper.js:JS图像裁剪库
前端·javascript
Serendipity26137 分钟前
微服务架构
前端·微服务
Hilaku1 小时前
深入background-image:你可能不知道的几个性能优化与高级技巧
前端·css
南岸月明1 小时前
副业自媒体1年终于明白:为什么会表达的人,能量越来越强,更能赚到钱?
前端
Danny_FD1 小时前
Vue + Element UI 实现模糊搜索自动补全
前端·javascript
gnip1 小时前
闭包实现一个简单Vue3的状态管理
前端·javascript