本地启动子应用接入,跨站请求Cookie携带的坑

891 阅读4分钟

我们部门对外提供了一个统一的基座,需要业务组自己去接入微前端项目。
所以最近要写一个接入微前端的demo项目给业务组去用。
本来以为是一个轻松愉快的过程,没想到踩了个天坑。

授权问题

原本的授权流程如下:

image.png

  1. 前端通过访问接口,后端检测没有登陆信息则返回授权地址
  2. 前端拿到授权地址,拼接授权成功回跳地址后进行跳转
  3. 授权成功,写入cookie,重新回跳到前端页面
  4. 重新访问接口,后端检测已授权,返回接口数据

拼接后的授权地址大致如下: https://gis-oauth.com/oauth2/authorize?response_type=code&scope=openid&state=xxxxx&client_id=xxxxx&redirect_uri=127.0.0.1:8080/login/oauth&target_uri=https://gis-console.com/microfrontend/WuvLKNl_7B/home

  • redirect_uri中间层跳转的地址
  • target_uri是前端自己拼接的回跳地址

但是: 127.0.0.1,我就把redirect_uri换成了demo.juejin.com(线上地址)。这样跳转授权都是成功的,但是tmd,cookie是写在demo.juejin.com下面。授权成功后,127.0.0.1是拿不到demo.juejin.com下面的cookie的。

于是乎:我们就想到了利用devServer进行一次代理,我就把redirect_uri不去修改,这样就会访问到我的前端服务器,我再劫持下/login/oauth,给他代理到线上服务(demo.juejin.com)去。这样是不是就骗过了浏览器?

devServer: {
    ....
    proxy: {
        ...
      // 用于授权代理到后端服务
      '^/login/oauth': {
        target: proxyTarget,
        changeOrigin: true,
      }
  },
}
  

跨域携带cookie问题

上面的方法干完后,我惊奇的发下cookie写入成功了,如果不使用主应用去访问,直接访问子应用(127.0.0.1:8080),授权流程就走通了,cookie也被带上了。。。

image.png 又但是: 我以为我骗过了浏览器,浏览器却云淡风轻的说:小伙子,你还是太年轻。。

我惊奇的发现,在主应用下,我的cookie是已经被写入了,但是我再请求的时候是没有带上cookie的。

image.png 相信大家一开始的想法都跟我一样,是不是withCredentials没设置啊,是不是代理服务器的响应头不允许withCredentials啊,检查了下,并没有毛病啊:

image.png

image.png 就因为我先入为主了这个想法,导致我四个小时疯狂改配置,什么domainRewrite,什么pathDomainRewite,全都试了一个遍。

跨域与跨站

首先,我们地启动前端服务器是做了跨域处理(CORS)的,所以在主应用下访问127.0.0.1是不会报跨域错误。而且我的前端服务器也是允许跨域带Cookie的。
但是现在去情况就是Cookie已经被写入到浏览器中,但是接口请求却无法给被带上。
经过我疯狂百度,发现了问题所在,那就是Chrome浏览器在80版本后,新加了一个跨站的概念。也就是说,跨域处理被我处理掉了,但是浏览器的跨站不能携带Cookie,却不能被处理。跨站如何解决传送门

image.png 所以有两条解决思路:

  1. 让浏览器认为我没有跨站,也就是需要本地绑定一个host,这个host需要跟主应用的域名同站,然后让host的地址指向127.0.0.1。但是由于我们公司的授权页面有白名单(127.0.0.1在白名单中),而我自己绑定的host不在白名单中,所以我用了第二种解决方案
  2. 让后端在写Cookie的时候,把sameSite给关了,这样浏览器就可以跨站传输Cookie了。
res.setHeader({
    name:'Set-Cookie',
    value:'xxxxxxx;Http-Only;SameSite=none;Secure'
})

顺便分享

由于服务器允许跨域携带Cookie的话,不能设置Access-Control-Allow-Origin为*,而且只能设置一个值。这就导致了,如果我想部署在两个域名下就不能实现的问题,对于nginx来说,可以通过$match来控制

image.png 如果本地启动的服务器怎么办呢,以vue-dev-server为例:

image.png header可以支持传入一个函数,可以接收req信息作为参数,然后return一个配置,这样做后,可以和nginx配置一样,配置多个Access-Control-Allow-Origin

总结

以前年纪小,吃够了跨域的苦,现在有一百种方法解决跨域。然后现在要吃跨站的苦。。。MD。。。。FUCK............