记录一次跨域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/, ''),  
    },  
  },  
},
相关推荐
吕彬-前端2 分钟前
使用vite+react+ts+Ant Design开发后台管理项目(二)
前端·react.js·前端框架
青灯文案18 分钟前
SpringBoot 项目统一 API 响应结果封装示例
java·spring boot·后端
小白小白从不日白23 分钟前
react hooks--useCallback
前端·react.js·前端框架
恩婧31 分钟前
React项目中使用发布订阅模式
前端·react.js·前端框架·发布订阅模式
mez_Blog32 分钟前
个人小结(2.0)
前端·javascript·vue.js·学习·typescript
珊珊而川40 分钟前
【浏览器面试真题】sessionStorage和localStorage
前端·javascript·面试
森叶1 小时前
Electron 安装包 asar 解压定位问题实战
前端·javascript·electron
drebander1 小时前
ubuntu 安装 chrome 及 版本匹配的 chromedriver
前端·chrome
微尘81 小时前
C语言存储类型 auto,register,static,extern
服务器·c语言·开发语言·c++·后端
软件技术NINI1 小时前
html知识点框架
前端·html