Skip to content

海外登录实践

背景

登录业务是软件出海业务中非常常见的一个业务,接下来我们将介绍常见的登录方案.

登录方案

因 HTTP 是一种无状态的协议,宏观上来看每次请求都是独立的,但实际上每次请求都会建立一个连接,在请求完成后又会断开这个连接。

这种方式可以节省传输时占用的连接资源,但同时也存在一个问题:每次请求都是独立的,服务器端无法判断本次请求和上一次请求是否来自同一个用户,进而也就无法判断用户的登录状态。

为了解决 HTTP 无状态的问题,Lou Montulli 在 1994 年的时候,推出了 Cookie。 Cookie 是服务器端发送给客户端的一段特殊信息,这些信息以文本的方式存放在客户端,客户端每次向服务器端发送请求时都会带上这些特殊信息。

在 B/S 系统中,登录功能通常会基于 Cookie 来实现的。因为当用户登录成功后,服务端一般会将登录状态记录到 Session 中。要实现服务端对客户端的登录信息进行验证,则需要在客户端保存 SessionId,并要求客户端在之后的每次请求中携带它们。在这样的场景下,使用 Cookie 是相当方便的,因此我们一般都会将 Session 的 Id 保存到 Cookie 中,当服务端收到请求后,通过验证 Cookie 中的信息来判断用户是否登录

实现流程

Cookie + Session 的登录方式是经典的一种登录方式,现在也存在大量的企业在使用。

用户首次登录时:

流程

  1. 用户访问 a.com/pageA,并输入密码登录。
  2. 服务器验证密码无误后,会创建 SessionId,并将它保存起来。
  3. 服务器端响应这个 HTTP 请求,并通过 Set-Cookie 头信息,将 SessionId 写入 Cookie 中
  4. 用户在后续的请求中,会自动携带 Cookie 中的 SessionId,服务器端通过 SessionId 来判断用户是否登录。

服务器端的 SessionId 可能存放在很多地方,例如:内存、文件、数据库等。

用户后续访问 a.com/pageA 时:

流程

  1. 用户访问 a.com/pageA,并自动携带 Cookie 中的 SessionId。
  2. 服务器端通过 SessionId 来判断用户是否登录。
  3. 如果用户已登录,则服务器端返回页面内容。
  4. 如果用户未登录,则服务器端返回登录页面。

小结

虽然我们可以使用 Cookie + Session 的方式完成了登录验证,但仍然存在一些问题:

  1. 由于服务器端需要对接大量的客户端,也就需要存放大量的 SessionId,这样会导致服务器压力过大。
  2. 如果服务器端是一个集群,为了同步登录态,需要将 SessionId 同步到每一台机器上,无形中增加了服务器端维护成本。

JWT 方案

为了解决 Cookie + Session 机制暴露出的诸多问题,我们可以使用 Token 的登录方式。

Token 是通过服务端生成的一串字符串,以作为客户端请求的一个令牌。当第一次登录后,服务器会生成一个 Token 并返回给客户端,客户端后续访问时,只需带上这个 Token 即可完成身份认证。

Token 机制实现流程

用户首次登录时

Token 机制实现流程

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

Token 机制实现流程

  1. 用户访问 a.com/pageB 时,带上第一次登录时获取的 Token。
  2. 服务器端验证该 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 的优缺点:

  1. 服务器端不需要存放 Token,所以不会对服务器端造成压力,即使是服务器集群,也不需要增加维护成本。
  2. 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 等多个业务系统。

  1. 为了提升用户体验,提供一致的登录体验,减少用户登录次数和心智成本。
  2. 为了提升效率,减少业务研发重复开发登录功能,需要实现品牌之间的多产品线的数据互通。
  3. 集中管理登录模块,可以更加方便的进行统一更新和安全策略的实施,便于后续的管理与维护,

基于此,海外业务背靠国内强大的 UC 团队,结合海外的业务场景,实现了 SSO 单点登录。

单点登录是指在同一帐号平台下的多个应用系统中,用户只需登录一次,即可访问所有相互信任的应用系统。本质就是在多个应用系统中共享登录状态。举例来说,By Class 和 By Meeting 是 By 公司旗下的两个不同的应用系统,如果用户在 By Class 登录过之后,当他访问 By Meeting 时无需再次登录。

SSO 机制实现方式

单点登录主要有三种实现方式:

  1. 父域 Cookie
  2. 认证中心

目前海外业务 SSO 实现方式是基于父域 Cookie 的方式实现的。

海外业务 SSO 实现流程

SSO 实现流程

  1. 用户访问网站 class.by.com
  2. 由于没有登录,则会重定向到 id.by.com,并带上回调地址以便登录后直接进入对应页面。
  3. 用户在认证中心输入账号密码,提交登录。
  4. 认证中心验证账号密码有效,然后重定向 class.by.com, 而登陆中心 id.by.com 将登录态写入 Cookie 中。
  5. 由于 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 是认证中心的,应用系统是访问不到的)

  1. 应用系统检查当前请求有没有 Token,如果没有,说明用户在当前系统中尚未登录,那么就将页面跳转至认证中心进行登录。
  2. 由于这个操作会将认证中心的 Cookie 自动带过去,因此,认证中心能够根据 Cookie 知道用户是否已经登录过了。如果认证中心发现用户尚未登录,则返回登录页面,等待用户登录,如果发现用户已经登录过了,就不会让用户再次登录了,而是会跳转回目标 URL ,并在跳转前生成一个 Token,拼接在目标 URL 的后面,回传给目标应用系统。
  3. 应用系统拿到 Token 之后,还需要向认证中心确认下 Token 的合法性,防止用户伪造。确认无误后,应用系统记录用户的登录状态,并将 Token 写入 Cookie,然后给本次访问放行。(这个 Cookie 是当前应用系统的,其他应用系统是访问不到的)当用户再次访问当前应用系统时,就会自动带上这个 Token,应用系统验证 Token 发现用户已登录,于是就不会有认证中心什么事了。

总结:此种实现方式相对复杂,支持跨域,扩展性好,是单点登录的标准做法。

OAuth2.0

在 OAuth2.0 中,一般会有 4 个角色:

  • 资源拥有者
    • 资源拥有者是拥有资源的人,例如用户。
  • 第三方软件(客户端应用)
    • 第三方软件客户端应用是请求资源的一方,例如浏览器。
  • 授权服务
    • 授权服务是授权资源的一方,例如认证中心。
  • 受保护资源
    • 受保护资源是受保护的资源,例如用户信息。

OAuth2.0 实现流程

扫码登录

扫码登录 实现流程