前言

ios14 默认关闭应用的 「允许跨站跟踪」的权限
微信浏览器没有提供 safari 和 chrome 等主流浏览器提供用户操作关闭「阻止跨网站跟踪」的功能

1、什么是跨域?

1.1 为什么会有跨域?

其实是出于浏览器的同源策略限制

  • 出于浏览器的同源策略 / SOP(Same origin policy)限制
  • 同源策略是一种约定,它是浏览器最核心也最基本的安全功能
  • Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现
  • 如果缺少了同源策略,浏览器很容易受到 XSS、CSRF 等攻击

    1.2 什么是跨域?

    源:协议、域名、端口

  • 同源就是两个页面具有相同的 协议 (protocol)、主机 (host) 和端口号 (port)

  • 当一个请求 url 的协议、域名、端口三者之间任意一个与当前页面 url 不同即为跨域

例如下表的 A 调用 B:

A URL BURL 是否跨域 原因
https://login.taobao.com/index.html https://login.taobao.com/home.php 协议、域名、端口号一致
http://login.taobao.com/index.html https://login.taobao.com/home.php 协议不同
https://cn.aliyun.com https://login.taobao.com 域名不同
http://login.taobao.com:8080 http://login.taobao.com:8081 端口号不同

2、解决跨域的几种方式

  • 通过 jsonp 跨域
  • document.domain + iframe 跨域
  • location.hash + iframe
  • window.name + iframe 跨域
  • postMessage 跨域
  • 跨域资源共享(CORS)
  • nginx 代理跨域
  • nodejs 中间件代理跨
  • WebSocket 协议跨域

    3、业务遇到的跨域问题

    3.1 问题背景

  • ios14 默认关闭应用的 「允许跨站跟踪」的权限

  • 而且微信浏览器没有提供 safari 和 chrome 等主流浏览器提供用户操作关闭「阻止跨网站跟踪」的功能。导致 ios14 的用户使用微信浏览器无法登录我们业务

用ticket解决跨域问题 - 图1

3.2 业务此前的登录流程

  1. 用户使用账号密码登录,登录成功后 登录平台 将用户 cookie 到 .abc.com 域名下
  2. 统一登录 redirect 到业务的 x.xyz.cn
  3. 但由于跨站跟踪的限制,业务的 x.xyz.cn 无法从 .abc.com下拿到用户 cookie (一级域名、二级域名均不同)
  4. 最终导致在 jsonp 去校验登录状态(checkLogin) 时,不能用 token 去跟统一登录后台换取 userInfo,登录校验不通过 x.xyz.cn 会⼀值停留在 redirect ⻚⾯

用ticket解决跨域问题 - 图2
为什么其它业务不出现上述情况?以 B 业务为例,看他们的登录方式:

  1. 用户使用账号密码登录 B,登录成功后 统一登录 将用户 cookieset 到 .abc.com 域名下
  2. 统一登录 redirect 到 B.abc.com 域名下
  3. 由于 B 与统一登录之间的 一级域名、二级域名均相同,B.abc.com 可以直接从 abc.com 下获取用户 token
  4. 最后通过 jsonp 去校验登录状态,用 token 去跟统一登录后台换取 userInfo

    4、跨域问题解决方案

    4.1 方案一

    方案:将我们业务的顶级域名 从 .cn 换成 .com、将二级域名 .xyz 换成 .abc
    优点:线上问题快速修复、解决跨域的根本问题
    问题:需要申请新域名、业务i在各处的备案信息均需要修改
    结果:产品经理、项目负责人等均否决此方案

    4.2 方案二(最终实现的方案)

    4.2.1 基本思路

    业务不直接从 .abc.com 域名下获取用户 token,而是通过 调接口的方式 去获取用户t oken

    4.2.2 实现流程

    用ticket解决跨域问题 - 图3

  5. 业务访问统一登录页面时,链接处携带 \withticket=true 参数,告知统一登录 业务的登录方式

  6. 统一登录知悉此种登录方式后,将会生成一个 ticket(类似于一个id) 返回到统一登录前端
  7. 统一登录前端通过 redirect 方式将生成的 ticket 给到 业务前端
  8. 业务前端根据获得的 ticket 在 node 层换取用户token(调用平台 server 获取 token)
  9. 业务前端在拿到用户 token 后,再去获取 userInfo (调用平台 server )
  10. 业务前端重定向到业务的页面(redirect_url),把 userInfo 设置 cookie 到 browser 中

    4.2.3 具体实现

  11. 业务前端拼接登录地址:登录域名+ ?withticket=true&redirect_url= + redirect 中继页 + 页面重定向 url

    1. withticket=true:告知统一登录业务将采用 ticket 的登录方式
    2. redirect 中继页:https://study.seewoedu.cn/redirect 用于截获 ticket 获取 token
  12. redirect 中继页中,有一个 redict controller,controller 将根据 ticket 去获取 token 、用 token 获取userInfo、set cookie