记录一次跨域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/, ''),  
    },  
  },  
},
相关推荐
Tech Synapse14 分钟前
Java根据前端返回的字段名进行查询数据的方法
java·开发语言·后端
.生产的驴14 分钟前
SpringCloud OpenFeign用户转发在请求头中添加用户信息 微服务内部调用
spring boot·后端·spring·spring cloud·微服务·架构
微信-since8119230 分钟前
[ruby on rails] 安装docker
后端·docker·ruby on rails
Myli_ing32 分钟前
考研倒计时-配色+1
前端·javascript·考研
余道各努力,千里自同风35 分钟前
前端 vue 如何区分开发环境
前端·javascript·vue.js
软件小伟44 分钟前
Vue3+element-plus 实现中英文切换(Vue-i18n组件的使用)
前端·javascript·vue.js
醉の虾1 小时前
Vue3 使用v-for 渲染列表数据后更新
前端·javascript·vue.js
张小小大智慧1 小时前
TypeScript 的发展与基本语法
前端·javascript·typescript
hummhumm1 小时前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j
asleep7012 小时前
第8章利用CSS制作导航菜单
前端·css