跳转到正文
Monster Cone
返回

Koa 跨域 Set-Cookie 不生效?CORS 场景排查与解决

编辑页面

后端 Set-Cookie 语句很简单,但遇到跨域时就会遇到各种各样的问题。正常情况下我们如下就可以很简单的给浏览器设置一个 cookie

ctx.cookies.set("accessToken", accessToken, {
  expires: new Date(accessTokenExpired),
  httpOnly: false,
});

httpOnly 默认是 true,如果你的 token 本身就是通过 cookie 传递解析可忽略,否则前端 js 无法获取到该 cookie。

在本地开发时并没有什么问题,但发布上线后,就会发现 cookie 无法写入。

1. 后端配置

后端使用 nginx 反向代理时,需要开启 Koa 框架的信任代理

const app = new Koa();
app.proxy = true;

在跨域情况下,Set-Cookie 必须配置 sameSite 和 secure 属性,示例如下

ctx.cookies.set("xxx", xxx, {
  expires: new Date(),
  httpOnly: false,
  secure: true,
  sameSite: "None",
  domain: ".dxin.cc",
});

如果前端域名和 API 域名不同,我们还需要配置 domain,domain 使用.xxx.xxx 的格式,保证你的前端域名和 API 域名都能匹配。

2. 前端配置

前端在请求时也必须携带 cookie 才行

axios 配置

const apiInstance = axios.create({
  baseURL:
    process.env.NODE_ENV === "production"
      ? "https://xxx-api.xxx.xxx/v1"
      : "/v1", // 设置API的基本URL
  timeout: 5000,
  withCredentials: true, // 携带Cookie
});

fetch 配置

fetch("https://xxx.xxx.xxx/v1", {
  credentials: "include", // 携带Cookie
});

它们默认都是不携带 cookie 的,如果不想在所有请求中都携带 cookie,可以在需要 Set-Cookie 的请求时配置即可。

3. Nginx 配置

server {
    server_name xxx-api.xxx.xxx;
    proxy_pass_header Set-Cookie;

    add_header Access-Control-Allow-Origin https://xxx.xxx.xxx always;
    add_header Access-Control-Allow-Credentials true always;

    ...othen config

    location / {
        ...other config
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

完成上述配置后,我们就跨域在请求得到响应时,在浏览器看到响应的 cookie。

当前文章并没有 CORS 配置,默认已经能够在 CORS 情况下请求成功。

常见的错误情况

1. 接口响应 200,但却出现 CORS 错误

这种情况下我们能看到接口响应了 200,但没有响应数据,并且 Set-Cookie 没有效果,这是因为我们配置了双重跨域,在 Nginx 和后端都开启了跨域。

这是因为 domain 无法匹配当前域名或者 expires 为当前时间导致被清空

最后,跨域 Set-Cookie 重点就是前端携带 cookie 请求,Nginx 允许携带 Credentials,domain 域名匹配,sameSite 为”None”。


编辑页面
分享这篇文章:

上一篇
Flutter App CI/CD 实战:用 GitHub Actions 自动构建与发布
下一篇
博客迁移实录:从 Hugo 到 Next.js + Tailwind CSS