海外登录实践
背景
登录业务是软件出海业务中非常常见的一个业务,接下来我们将介绍常见的登录方案.
登录方案
Session + Cookie 方案
因 HTTP 是一种无状态的协议,宏观上来看每次请求都是独立的,但实际上每次请求都会建立一个连接,在请求完成后又会断开这个连接。
这种方式可以节省传输时占用的连接资源,但同时也存在一个问题:每次请求都是独立的,服务器端无法判断本次请求和上一次请求是否来自同一个用户,进而也就无法判断用户的登录状态。
为了解决 HTTP 无状态的问题,Lou Montulli 在 1994 年的时候,推出了 Cookie。 Cookie 是服务器端发送给客户端的一段特殊信息,这些信息以文本的方式存放在客户端,客户端每次向服务器端发送请求时都会带上这些特殊信息。
在 B/S 系统中,登录功能通常会基于 Cookie 来实现的。因为当用户登录成功后,服务端一般会将登录状态记录到 Session 中。要实现服务端对客户端的登录信息进行验证,则需要在客户端保存 SessionId,并要求客户端在之后的每次请求中携带它们。在这样的场景下,使用 Cookie 是相当方便的,因此我们一般都会将 Session 的 Id 保存到 Cookie 中,当服务端收到请求后,通过验证 Cookie 中的信息来判断用户是否登录
实现流程
Cookie + Session 的登录方式是经典的一种登录方式,现在也存在大量的企业在使用。
用户首次登录时:

- 用户访问 a.com/pageA,并输入密码登录。
- 服务器验证密码无误后,会创建 SessionId,并将它保存起来。
- 服务器端响应这个 HTTP 请求,并通过 Set-Cookie 头信息,将 SessionId 写入 Cookie 中
- 用户在后续的请求中,会自动携带 Cookie 中的 SessionId,服务器端通过 SessionId 来判断用户是否登录。
服务器端的 SessionId 可能存放在很多地方,例如:内存、文件、数据库等。
用户后续访问 a.com/pageA 时:

- 用户访问 a.com/pageA,并自动携带 Cookie 中的 SessionId。
- 服务器端通过 SessionId 来判断用户是否登录。
- 如果用户已登录,则服务器端返回页面内容。
- 如果用户未登录,则服务器端返回登录页面。
小结
虽然我们可以使用 Cookie + Session 的方式完成了登录验证,但仍然存在一些问题:
- 由于服务器端需要对接大量的客户端,也就需要存放大量的 SessionId,这样会导致服务器压力过大。
- 如果服务器端是一个集群,为了同步登录态,需要将 SessionId 同步到每一台机器上,无形中增加了服务器端维护成本。
JWT 方案
为了解决 Cookie + Session 机制暴露出的诸多问题,我们可以使用 Token 的登录方式。
Token 是通过服务端生成的一串字符串,以作为客户端请求的一个令牌。当第一次登录后,服务器会生成一个 Token 并返回给客户端,客户端后续访问时,只需带上这个 Token 即可完成身份认证。
Token 机制实现流程
用户首次登录时

- 用户访问 a.com/pageA,输入账号密码,并点击登录。
- 服务器端验证账号密码无误,创建 Token。
- 服务器端将 Token 返回给客户端,由客户端进行存储。
后续页面访问时

- 用户访问 a.com/pageB 时,带上第一次登录时获取的 Token。
- 服务器端验证该 Token ,有效则身份验证成功,无效则踢回重新的登录。
Token 生成方式
最常见的 Token 生成方式是使用 JWT(Json Web Token),它是一种简洁的、自包含的方法,用于通信双方之间以 JSON 对象的形式安全的传递信息。 使用 Token 后,服务器端并不会存储 Token,那怎么判断客户端发过来的 Token 是合法有效的呢? 答案其实就在 Token 字符串中,其实 Token 并不是一串杂乱无章的字符串,而是通过多种算法拼接组合而成的字符串。
JWT 算法主要分为 3 个部分:
- header(头信息): 指定该 JWT 使用的签名算法
- playload(消息体): 表明了 JWT 的意图
- signature(签名): 为 JWT 的签名,主要为了让 JWT 不能被随意篡改
关于 JWT,这里简单说明一下,具体细节大家可以去看一下 (JWT 官网)[https://www.jwt.io/introduction]。
小结
根据上面的案例,我们可以分析出 Token 的优缺点:
- 服务器端不需要存放 Token,所以不会对服务器端造成压力,即使是服务器集群,也不需要增加维护成本。
- Token 下发之后,只要在生效时间之内,就一直有效,但是如果服务器端想收回此 Token 的权限,并不容易。
有了 Token 之后,登录方式已经变得非常高效。
海外业务的登录凭证目前也是采用的 JWT 方案,但因海外业务用户存在数据安全合规、多集群的场景,并且不同集群之前的数据无法互通,因此在生成 Token 时,需要将用户信息和集群信息一起生成 Token,在验证 Token 时,会根据 Token 中的集群信息路由到对应的集群进行鉴权。
5 开头是欧洲集群, 4 开头是新加坡集群, 3 开头是美西集群
目前统一登录会通过 Redis 进行缓存 + 鉴权,进而判断用户是否登录,解决 Token 实时性问题。
SSO
在软件出海过程中, OBM、ODM 业务衍射出了许多品牌业务,例如 By、MAX 等等,各个品牌内部存在多个业务系统,例如 By 内部存在 By Class、By Meeting、By Spark 等多个业务系统。
- 为了提升用户体验,提供一致的登录体验,减少用户登录次数和心智成本。
- 为了提升效率,减少业务研发重复开发登录功能,需要实现品牌之间的多产品线的数据互通。
- 集中管理登录模块,可以更加方便的进行统一更新和安全策略的实施,便于后续的管理与维护,
基于此,海外业务背靠国内强大的 UC 团队,结合海外的业务场景,实现了 SSO 单点登录。
单点登录是指在同一帐号平台下的多个应用系统中,用户只需登录一次,即可访问所有相互信任的应用系统。本质就是在多个应用系统中共享登录状态。举例来说,By Class 和 By Meeting 是 By 公司旗下的两个不同的应用系统,如果用户在 By Class 登录过之后,当他访问 By Meeting 时无需再次登录。
SSO 机制实现方式
单点登录主要有三种实现方式:
- 父域 Cookie
- 认证中心
1. 父域 Cookie
目前海外业务 SSO 实现方式是基于父域 Cookie 的方式实现的。
海外业务 SSO 实现流程

- 用户访问网站 class.by.com
- 由于没有登录,则会重定向到 id.by.com,并带上回调地址以便登录后直接进入对应页面。
- 用户在认证中心输入账号密码,提交登录。
- 认证中心验证账号密码有效,然后重定向 class.by.com, 而登陆中心 id.by.com 将登录态写入 Cookie 中。
- 由于 class.by.com 存在已登录的 Cookie 信息,所以服务器端直接认证成功。
这里主要是利用了 Cookie 的一个特点,即父域中的 Cookie 被子域所共享,也就是说,子域会自动继承父域中的 Cookie。 利用 Cookie 的这个特点,可以将 Session Id(或 Token)保存到父域中就可以了,这样所有的子域应用就都可以访问到这个 Cookie 了。 不过这要求应用系统的域名需建立在一个共同的主域名之下,如 id.by.com 和 class.by.com,它们都建立在 by.com 这个主域名之下,那么它们就可以通过这种方式来实现单点登录。
总结:此种实现方式比较简单,但不支持跨主域名。
2. 认证中心
我们可以部署一个认证中心,认证中心就是一个专门负责处理登录请求的独立的 Web 服务。

用户统一在认证中心进行登录,登录成功后,认证中心记录用户的登录状态,并将 Token 写入 Cookie。(注意这个 Cookie 是认证中心的,应用系统是访问不到的)
- 应用系统检查当前请求有没有 Token,如果没有,说明用户在当前系统中尚未登录,那么就将页面跳转至认证中心进行登录。
- 由于这个操作会将认证中心的 Cookie 自动带过去,因此,认证中心能够根据 Cookie 知道用户是否已经登录过了。如果认证中心发现用户尚未登录,则返回登录页面,等待用户登录,如果发现用户已经登录过了,就不会让用户再次登录了,而是会跳转回目标 URL ,并在跳转前生成一个 Token,拼接在目标 URL 的后面,回传给目标应用系统。
- 应用系统拿到 Token 之后,还需要向认证中心确认下 Token 的合法性,防止用户伪造。确认无误后,应用系统记录用户的登录状态,并将 Token 写入 Cookie,然后给本次访问放行。(这个 Cookie 是当前应用系统的,其他应用系统是访问不到的)当用户再次访问当前应用系统时,就会自动带上这个 Token,应用系统验证 Token 发现用户已登录,于是就不会有认证中心什么事了。
总结:此种实现方式相对复杂,支持跨域,扩展性好,是单点登录的标准做法。
OAuth2.0
在 OAuth2.0 中,一般会有 4 个角色:
- 资源拥有者
- 资源拥有者是拥有资源的人,例如用户。
- 第三方软件(客户端应用)
- 第三方软件客户端应用是请求资源的一方,例如浏览器。
- 授权服务
- 授权服务是授权资源的一方,例如认证中心。
- 受保护资源
- 受保护资源是受保护的资源,例如用户信息。

扫码登录
