记http项目A使用iframe嵌套http项目B携带cookie失败

470 阅读2分钟

1、前言

在某次项目中遇见http使用iframe嵌套http时,登录一直失败,经过排查,是发送请求时cookie未被携带过去,在响应头中的set-Cookie报了这样一个警告⚠️:

This Set-Cookie header didn't specify a "SameSite" attribute and was defaulted to "SameSite=Lax," and was blocked because it come from a cross-site response which was not the response to a top-level navigation. The Set-Cookie had to have been set with "SameSite=None" to enable cross-site usage.

错误信息表明浏览器将 Cookie 的 SameSite 属性默认为 Lax,这意味着 Cookie 只能在同源或顶层导航请求中发送,而不能在跨站请求中发送。为解决此问题,必须在 服务器端 设置 SameSite=NoneSecure 属性。

问题到这,解决方案已经很明朗了:

proxy_cookie_path / "/; httponly; secure; SameSite=None";
  • SameSite=Strict:仅允许同源请求携带 cookie。

  • SameSite=Lax:允许某些跨站请求,但对于第三方请求可能会被阻止。

  • SameSite=None:不限制跨站请求,但要求 Secure=true

但是,需要注意的是,这样设置,如果 Secure=true,则只有在 HTTPS 请求时,浏览器才会发送该 cookie。若前端使用的是 HTTP 协议,cookie 将不会被发送。

不幸的是,客户强制要求使用http,还是甲方牛,下辈子争取当甲方!

2、解决方案

2.1、改用https

被pass了

2.2、认证方式修改为token

开发时间长,又被pass了

2.3、服务端nginx代理

在A项目中将原来iframesrc由具体的链接/IP地址修改为${location.origin}/kylin/xxx,并在A项目的nginx进行配置转发/kylin开头的请求

2.3.1、A项目修改iframenginx

根据具体情况来,以下是笔者的配置

`${location.origin}/dasapi/overview`
# 排除特定路径
location ~* ^/kylin/(js|css|fonts)/ {
  proxy_pass http://xxxxx;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;
}
# 重写 /kylin/xx 为 /xx
location ~* ^/kylin/(?!js|css|fonts|ace)(.*)$ {
  rewrite ^/kylin/(.*)$ /$1 break;
  proxy_pass http://xxxxx;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;
}
# 其他请求前缀为 /audit-apiv2/、/risk-platform/、/report-api/、/audit-report/
location ~* ^/(audit-apiv2|risk-platform|report-api|audit-report)/ {
  proxy_pass http://xxxxx;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;
}

2.3.2、B项目修改publicPath

  • 首先,需要给静态资源加上一个前缀,比如:/kylin,修改vue.config.js文件中的publicPath,这样打包后的静态资源都会加上/kylin这个前缀
module.exports = {
  publicPath: '/dasapi',
  lintOnSave: true,
  assetsDir: './',
}

image.png

  • 如此一来,我们在部署完时去访问,会报这些静态资源404的问题,那么还需要在nginx配置一下静态资源的代理,根据我的项目而言,是部署在root根目录下的webapp文件夹下,那么添加的配置如下:
location /kylin/js/ {
  alias /webapp/dist/js/;
}
location /kylin/css/ {
  alias /webapp/dist/css/;
}                    
location /kylin/fonts/ {
  alias /webapp/dist/fonts/;
}
  • 如果到这步就部署了,那么大概率会遇到跳转到空白页面或者error页面的情况

2.3.3、router添加base路径

const router = new Router({
  base: '/kylin'
})

这个给整个url加统一的前缀,因为iframesrc值以该base路径为前缀,在进入到我们项目的beforeEach时,第一次中的to.path仍然是/kylin/xxx,如果没有加base路径的话,将无法匹配,页面将导致空白或者到error页面

到此结束。