第5章用户登录服务——5.5 第三方登录

OAuth2.0 协议原理

第三方登录指的是基于用户在第三方平台已有的账号和密码来快速完成乙方应用的注册与登录功能。这里的第三方平台一般是指已经拥有大量用户的知名平台,比如微信、微博、支付宝、QQ等。第三方登录具有如下优势。

  • 快速登录:用户无须花费时间记忆和输入账号、密码,通过第三方平台的账号授权即可完成身份验证。
  • 账号安全:第三方登录可以帮助用户保护账号在乙方应用中的安全,比如防止账号被盗等。
  • 提升用户体验:第三方登录允许不同的网站或应用共享同一条登录信息,让用户可以更便捷地使用各种应用。例如,微信用户可以使用微信登录大众点评、拼多多、腾讯视频、小红书等应用。
  • 用户数据分析:第三方登录平台可以帮助乙方应用有效地跟踪用户,并对用户数据进行智能分析和挖掘,为用户提供更具针对性和有价值的产品与服务。

5.5.1 OAuth2 标准

目前市面上主流的第三方登录协议是OAuth2,它是一个开放的授权标准,允许用户授权乙方应用访问他们存储在第三方平台的信息,而不需要将第三方平台的用户名和密码提供给乙方应用。微信、微博、QQ等提供第三方登录的开放平台都遵循OAuth 2标准。

乙方应用必须先得到用户的授权,才能访问用户在第三方平台的信息。OAuth2提供了多种用户授权模式,这里需要重点介绍的是授权码模式,它是功能最为完整、流程最为严格的授权模式。在此授权模式下,OAuth2标准定义了4种角色。

  • 资源所有者:代表希望第三方登录的终端用户。
  • 资源服务器:第三方登录服务提供商用于存放受保护的用户资源的服务器,访问这些用户资源需要获取访问令牌(Access Token)。典型的用户资源包括头像、昵称、联系人列表等。
  • 授权服务器:负责验证资源所有者,下发访问令牌。
  • 客户端:乙方应用。

使用授权码模式完成微信账号授权的流程如下所述,如图5-5所示。

image-20250322103247414

  1. 用户在客户端选择微信登录,跳转到微信登录页面,请求用户授权。
  2. 用户在微信登录页面确认授权,于是微信会给客户端提供一个授权码。
  3. 客户端得到授权码,向微信授权服务器发送请求获取访问令牌。
  4. 如果客户端身份和授权码验证通过,则授权服务器为客户端返回访问令牌。
  5. 客户端使用访问令牌从资源服务器中获取用户资源。
  6. 如果访问令牌验证通过,则资源服务器返回用户资源给客户端。

5.5.2 客户端接入第三方登录

与手机号一键登录类似,比如我们的应用Friendy想接入微信第三方登录,首先要做的事情就是去微信开放平台以开发者身份申请接入,这是几乎所有应用使用第三方服务所必需的步骤。在微信开放平台填写应用相关信息并提交申请,微信相关工作人员审核通过后,我们就可以获得AppID和AppSecret,这是应用Friendy可以调用微信第三方登录的官方认证。

接下来,我们就可以开始在客户端接入第三方登录流程了,如图5-6所示。

image-20250322103613045

  1. Friendy客户端开发者需要先引入微信提供的SDK,然后通过SDK完成微信唤起与用户授权的流程。

  2. 用户选择微信登录时,Friendy客户端调用SDK唤起微信客户端,同时将AppID等信息传递给微信服务端,由微信服务端检查AppID是否已在微信开放平台注册;

  3. 如果微信服务端确认无误,则将授权信息返回给微信客户端,由用户在微信内登录(如果已经登录,则不需要这一步)并确认授权,

  4. 用户同意授权后请求微信服务端生成授权码,微信服务端响应后唤起Friendy客户端并返回授权码。

  5. 至此,OAuth2标准的获取授权码环节就完成了,Friendy客户端可以使用授权码继续授权流程。

5.5.3 服务端接入第三方登录

下面是服务端接入第三方登录流程。

  1. Friendy客户端获取到授权码后,紧接着需要获取访问令牌。
  2. Friendy客户端先将授权码告知Friendy服务端,由Friendy服务端使用授权码、AppID、AppSecret从微信服务端(特指微信的授权服务器)获取访问令牌;
  3. 微信服务端验证AppID、AppSecret已注册,且授权码有效后,会返回对应用户的访问令牌和openID。openlD是用户在第三方平台的唯一身份标识,使用第三方登录时,每个第三方平台用户都有一个独一无二的openID。
  4. Friendy服务端得到openlD和访问令牌后,接下来就可以通过访问令牌从微信服务端获取用户身份信息了。

至此,OAuth2标准的获取访问令牌和获取用户资源的环节也就都完成了。

不过,这时我们获取到的用户信息毕竟是第三方的,第三方用户信息不一定能满足我们的业务需要。比如第三方用户使用openlD标识,如果我们直接将其作为用户ID,那么需要考虑以下两个方法:

  • 用户ID一般用64位整数表示,而openlD普遍采用字符串形式;
  • 微信用户openlD可能与微博用户openlD相同,我们无法保证不同第三方平台的用户openlD也一定不同。

我们需要为新加入的第三方登录用户创建符合系统的用户信息,其方式与手机号登录、邮箱登录的方式相同,即在数据库中创建一个第三方授权表User_auth_3rd,如表5-3所示。

image-20250322104138595

如果某个微信用户从未登录过我们的系统,那么首次登录时需要创建系统用户账号。所以,Friendy服务端得到openlD和访问令牌时,需要先查询openlD在User_auth_3rd表中是否存在。SQL 语句为SELECT * FROM User_auth_3rd WHERE open_id='openID' AND auth_type=1

如果没有记录存在,则需要创建新用户ID,将微信授权信息插入User_auth_3rd表中,然后使用访问令牌从微信服务端获取用户信息,保存到User表中。

如果有记录存在,则说明该微信用户曾经登录过系统,且对应的系统用户ID是user_id字段值,我们就直接将此用户ID作为登录者。同时,若访问令牌尚未过期,则无须再从微信服务端获取用户信息;若访问令牌已过期,则需要更新访问令牌并重新获取用户信息。

至此,微信用户第三方登录完成。

5.5.4 第三方登录的完整流程总结

第三方登录的完整流程如下所述,如图5-7所示。

image-20250322104502303

  1. 用户打开Friendy客户端,选择微信登录。
  2. Friendy客户端调用微信SDK,唤起本机安装的微信客户端登录页。
  3. 微信客户端将注册过的AppID信息发送到微信服务端。
  4. 微信服务端验证AppID通过,允许此AppID第三方登录服务,将授权信息下发到微信客户端登录页。
  5. 用户对授权信息进行确认,发送请求到微信服务端。
  6. 微信服务端得到用户确认,下发授权码,微信客户端切回到Friendy客户端。
  7. Friendy客户端将授权码发送到Friendy服务端。
  8. Friend服务端向微信服务端请求访问令牌,传入AppKey、AppSecret和授权码。
  9. 微信服务端验证AppKey、AppSecret通过,Friendy服务端有权限使用第三方登录服务,且授权码有效,于是返回用户openlD和访问令牌。
  10. Friendy服务端得到openlD和访问令牌,先在第三方授权表User_auth_3rd中查询此微信openlD是否有记录。
  11. 如果查询到记录,且记录的访问令牌仍在有效期内,则直接登录成功。
  12. 如果未查询到记录,或者在查询到的记录中访问令牌已过期,则携带最新得到的访问令牌访问微信服务端。
  13. 微信服务端验证访问令牌合法,返回对应的用户信息。
  14. Friendy服务端更新第三方授权表User_auth_3rd和用户表User,登录完成。

需要强调的是,虽然本节一直用微信做第三方平台、用Friendy做乙方应用,但实际上微信开放平台提供的第三方登录服务不一定与上述流程完全对应,真正的乙方应用在接入第三方登录时也可能有其他交互行为,只不过它们的实现与上述流程大差不差,都遵循OAuth 2标准完成用户认证与授权。

总结

什么是第三方登录?

  • 第三方登录指的是基于用户在第三方平台已有的账号和密码来快速完成乙方应用的注册与登录功能。
  • 这里的第三方平台一般是指已经拥有大量用户的知名平台,比如微信、微博、支付宝、QQ等。

第三方登录具有哪些优势?

  • 快速登录:用户无须花费时间记忆和输入账号、密码,通过第三方平台的账号授权即可完成身份验证。
  • 账号安全:第三方登录可以帮助用户保护账号在乙方应用中的安全,比如防止账号被盗等。
  • 提升用户体验:第三方登录允许不同的网站或应用共享同一条登录信息,让用户可以更便捷地使用各种应用。例如,微信用户可以使用微信登录大众点评、拼多多、腾讯视频、小红书等应用。
  • 用户数据分析:第三方登录平台可以帮助乙方应用有效地跟踪用户,并对用户数据进行智能分析和挖掘,为用户提供更具针对性和有价值的产品与服务。

什么是OAuth2协议呢?

  • OAuth2是一个开放的授权标准,允许用户授权乙方应用访问他们存储在第三方平台的信息,而不需要将第三方平台的用户名和密码提供给乙方应用。

授权码模式下有哪4种角色?

  • 资源所有者:代表希望第三方登录的终端用户。
  • 资源服务器:第三方登录服务提供商用于存放受保护的用户资源的服务器,访问这些用户资源需要获取访问令牌(Access Token)。典型的用户资源包括头像、昵称、联系人列表等。
  • 授权服务器:负责验证资源所有者,下发访问令牌。
  • 客户端:乙方应用。

使用授权码模式完成微信账号授权的流程?

  1. 用户在客户端选择微信登录,跳转到微信登录页面,请求用户授权。
  2. 用户在微信登录页面确认授权,于是微信会给客户端提供一个授权码。
  3. 客户端得到授权码,向微信授权服务器发送请求获取访问令牌。
  4. 如果客户端身份和授权码验证通过,则授权服务器为客户端返回访问令牌。
  5. 客户端使用访问令牌从资源服务器中获取用户资源。
  6. 如果访问令牌验证通过,则资源服务器返回用户资源给客户端。

客户端接入第三方登录流程?

  1. Friendy客户端开发者需要先引入微信提供的SDK,然后通过SDK完成微信唤起与用户授权的流程。

  2. 用户选择微信登录时,Friendy客户端调用SDK唤起微信客户端,同时将AppID等信息传递给微信服务端,由微信服务端检查AppID是否已在微信开放平台注册;

  3. 如果微信服务端确认无误,则将授权信息返回给微信客户端,由用户在微信内登录(如果已经登录,则不需要这一步)并确认授权,

  4. 用户同意授权后请求微信服务端生成授权码,微信服务端响应后唤起Friendy客户端并返回授权码。

  5. 至此,OAuth2标准的获取授权码环节就完成了,Friendy客户端可以使用授权码继续授权流程。

服务端接入第三方登录流程?

  1. Friendy客户端获取到授权码后,紧接着需要获取访问令牌。
  2. Friendy客户端先将授权码告知Friendy服务端,由Friendy服务端使用授权码、AppID、AppSecret从微信服务端(特指微信的授权服务器)获取访问令牌;
  3. 微信服务端验证AppID、AppSecret已注册,且授权码有效后,会返回对应用户的访问令牌和openID。openlD是用户在第三方平台的唯一身份标识,使用第三方登录时,每个第三方平台用户都有一个独一无二的openID。
  4. Friendy服务端得到openlD和访问令牌后,接下来就可以通过访问令牌从微信服务端获取用户身份信息了。

第三方登录的完整流程?

  1. 用户打开Friendy客户端,选择微信登录。
  2. Friendy客户端调用微信SDK,唤起本机安装的微信客户端登录页。
  3. 微信客户端将注册过的AppID信息发送到微信服务端。
  4. 微信服务端验证AppID通过,允许此AppID第三方登录服务,将授权信息下发到微信客户端登录页。
  5. 用户对授权信息进行确认,发送请求到微信服务端。
  6. 微信服务端得到用户确认,下发授权码,微信客户端切回到Friendy客户端。
  7. Friendy客户端将授权码发送到Friendy服务端。
  8. Friend服务端向微信服务端请求访问令牌,传入AppKey、AppSecret和授权码。
  9. 微信服务端验证AppKey、AppSecret通过,Friendy服务端有权限使用第三方登录服务,且授权码有效,于是返回用户openlD和访问令牌。
  10. Friendy服务端得到openlD和访问令牌,先在第三方授权表User_auth_3rd中查询此微信openlD是否有记录。
  11. 如果查询到记录,且记录的访问令牌仍在有效期内,则直接登录成功。
  12. 如果未查询到记录,或者在查询到的记录中访问令牌已过期,则携带最新得到的访问令牌访问微信服务端。
  13. 微信服务端验证访问令牌合法,返回对应的用户信息。
  14. Friendy服务端更新第三方授权表User_auth_3rd和用户表User,登录完成。