面试官:如何实现扫码登录功能?
扫码登录原理
扫码登录的原理
场景题:二维码扫码登录设计
很多互联网产品不仅提供了移动端应用,还提供了PC端应用或网页访问方式,比如爱奇艺、腾讯视频等视频类产品,以及淘宝、微信等国民级产品。这些兼顾PC端用户体验的产品一般都提供了扫码登录功能:如果用户已在移动端登录,那么在PC端可以通过在移动端应用内扫描二维码的方式完成一键登录。
手机扫码登录方式具有方便快捷、安全性高、密码管理成本低、用户体验好等优势,后面我们会讨论这个功能的技术实现。
5.7.1 二维码二维码是一种可以存储大量信息的矩阵条形码,最早是在1994年由一家日本公司发明的。随着移动互联网的发展,二维码得到了非常广泛的发展和应用。
二维码采用特殊的编码方式将数字信息编码成黑白相间的矩阵图案,且编码方式多种多样,例如QR码、Data Matrix码等。使用扫描仪设备或相机对二维码进行扫描,可以将二维码解码转换回数字信号。二维码种类繁多,这里我们仅需要知道一段数据可以被编码生成二维码图片,使用手机扫描二维码图片可以将其解码回原始数据即可。
5.7.2 扫码登录的场景介绍假设小A是Friendy产 ...
客户端与服务端之间的通信是基于HTTP的,而HTTP是无状态的,即客户端每次发出请求时都永远无法得知上一次请求的状态数据,任何请求之间都是相互隔离的。比如客户端发起一次用户登录请求,之后再发起请求时并不知晓用户已经登录,更不知道自己的请求来自哪个用户。
然而,请求是否是已登录用户发起的是一个强诉求,对于绝大多数的写数据请求(如关注某人、发文章、发评论、转账等)来说,服务端都必须要求从请求中能识别出发起的用户,不然服务端根本不知道这些请求应该为谁执行;对于读数据请求也应该有类似的诉求。因此,所有的客户端请求都应该携带某些数据,以便服务端能够判断请求的发起者是否已登录,以及对应的用户ID。
这个问题似乎很容易解决:用户登录后,客户端把返回的用户ID保存起来,然后每次发起请求时都将用户ID强制作为参数之一传递即可。但是这种做法太过直白,任何稍有HTTP知识的人都可以把作为参数的用户ID随意修改后发送给服务端,使用户受到攻击。比如某个黑客通过本地网络抓包工具得知查询用户账户余额的HTTP path是api.friendy.com/wallet/get?user_id=xxx,他将任意用户ID作 ...
OAuth2.0 协议原理
第三方登录指的是基于用户在第三方平台已有的账号和密码来快速完成乙方应用的注册与登录功能。这里的第三方平台一般是指已经拥有大量用户的知名平台,比如微信、微博、支付宝、QQ等。第三方登录具有如下优势。
快速登录:用户无须花费时间记忆和输入账号、密码,通过第三方平台的账号授权即可完成身份验证。
账号安全:第三方登录可以帮助用户保护账号在乙方应用中的安全,比如防止账号被盗等。
提升用户体验:第三方登录允许不同的网站或应用共享同一条登录信息,让用户可以更便捷地使用各种应用。例如,微信用户可以使用微信登录大众点评、拼多多、腾讯视频、小红书等应用。
用户数据分析:第三方登录平台可以帮助乙方应用有效地跟踪用户,并对用户数据进行智能分析和挖掘,为用户提供更具针对性和有价值的产品与服务。
5.5.1 OAuth2 标准目前市面上主流的第三方登录协议是OAuth2,它是一个开放的授权标准,允许用户授权乙方应用访问他们存储在第三方平台的信息,而不需要将第三方平台的用户名和密码提供给乙方应用。微信、微博、QQ等提供第三方登录的开放平台都遵循OAuth 2标准。
乙方应用必须 ...
大部分互联网应用都支持手机号登录和邮箱登录的功能,这不仅仅使登录方式多样化,更重要的是,使用手机和邮箱往往具有如下优势。
用户习惯:人们在日常生活中通常使用手机和邮箱进行通信,互联网用户更是习惯使用固定的手机号或邮箱地址作为登录凭证,而不是花费心思去记住自己的各种账号与密码。
数据唯一:一个手机号只会属于一个用户,不存在多个用户使用同一个手机号的情况。对于邮箱也是如此。使用手机和邮箱可以免去冗长的账号注册流程,降低用户使用门槛。
身份认证:使用手机和邮箱能对用户进行身份认证,确保用户身份合法。
数据安全:手机和邮箱通常与用户数据权限关联,当用户忘记密码时,使用它们可以有效缩短找回密码的流程,提高账号的安全性。
总之,提供手机号登录和邮箱登录功能的目的是方便用户快速、安全地登录,提升用户体验,降低用户使用门槛。
5.4.1 数据表设计为了支持以手机号、邮箱等类似方式登录的功能,在数据库中需要额外创建一个用户授权表User_auth,如表5-2所示。
User_auth表与User表是多对一的关系,且有两个索引。
auth_id索引:根据手机号或邮箱地址查询授权记录,找到对应的用 ...
无论是客户端与服务端之间通过网络传输密码,还是将密码保存到数据库中,都需要保证密码安全。
5.3.1 使用HTTPS通信首先我们来解决客户端发送注册、登录请求到服务端时,防止第三方抓包工具获取到密码的问题。客户端与服务端之间使用HTTPS通信。HTTPS是身披SSL外壳的HTTP,在HTTP通信链路中利用SSL/TLS建立全信道加密数据包,在请求传输过程中,第三方抓包工具看到的是密文,所以获取不到密码。
需要注意的是,使用HTTPS并不能彻底保证密码安全,因为HTTPS的加密、解密行为发生在HTTP层和TCP层之间,如图5-1所示。
这就意味着,虽然HTTPS在网络传输过程中可以保证数据是密文,但是数据包到达服务端后,一旦经过解密进入HTTP层,数据就会变为明文,这时如果攻击者入侵服务端并在网络层拦截数据,那么依然可以获取到密码。攻击者入侵客户端同样可以获取到密码,况且客户端被入侵的可能性远大于服务端被入侵的可能性。所以需要强调的是,HTTPS保证的是数据在传输过程中的安全性,而攻击者依然可以在客户端和服务端拦截数据得到明文密码。
5.3.2 非对称加密为了防止用户密码在客 ...
用户登录服务负责用户的注册与登录,这是一个看似非常简单、很容易设计的服务。在学习数据库的过程中,很多同学都做过数据库的各种管理系统课程设计,比如图书馆管理系统、学生成绩管理系统等,使用数据库作为数据存储系统,使用HTTP协议的HTML页面作为用户操作界面。无论哪个管理系统,必不可少的一个功能都是用户注册与登录。当时,大家实现这个功能的方式基本如下。
首先,在数据库中创建一个用户表User来记录用户账号、密码和用户状态等信息,如表5-1所示(注意:用户昵称、头像、个性签名等这里暂不列出,它们不是用户登录服务的重点)。
然后,开发用户注册页面和登录页面。页面元素如下。
账号文本框:用户在此输入账号。
密码文本框:用户在此输入密码。
验证码标签:用户打开页面时,网页随机生成一个验证码并展示。
验证码文本框:用户在此输入验证码。
注册按钮:用户点击后注册。
登录按钮:用户点击后登录。
用户注册的流程如下。
用户打开注册页面,并在上述三个文本框中依次输入待注册的账号(如abc)、密码(如123456)和验证码。
用户点击注册按钮,HTTP使用POST方式将用户填入的账号、密码提交到后台。 ...
从本章开始,我们正式与用户相关服务打交道。当用户想使用一个互联网产品的完整功能时,要做的第一件事情就是在应用中注册账号并登录。这个功能由用户登录服务负责, 也是本章的主题。在正式学习用户登录服务前,我们先来了解本章的学习路径与内容组织结构。
5.1节介绍用户账号对互联网产品的意义。
5.2节介绍用户登录服务的功能要点。
5.3节介绍如何对用户密码进行最大可能的保护。
5.4节介绍手机号登录和邮箱登录的实现方式。
5.5节介绍第三方登录的实现方式。
5.6节介绍登录态问题以及登录态管理的方案。
5.7节介绍扫码登录的实现方式。
本章关键词:单向加密、用户认证、手机号一键登录、第三方登录、Session、长短令牌、扫码登录。
在早期互联网时代,大部分互联网产品是不需要用户注册与登录的。因为早期互联网产品主要是信息发布与浏览的平台,比如门户网站、搜索引擎,当时的用户行为非常简单(几乎就是浏览),不需要为用户提供个性化服务,所以不需要识别用户,更不需要用户注册与登录。
而随着互联网的发展,用户数量逐渐增加,用户的需求与行为也变得多样化和个性化,互联网产品开始逐渐转向注重社交性、交互性、个性 ...
Leaf是美团点评公司基础研发平台推出的一个唯一ID生成器服务,其具备高可靠性、低延迟、全局唯一等特点,目前已经被广泛应用于美团金融、美团外卖、美团酒旅等多个部门。Leaf根据不同业务的需求分别实现了Leaf-segment和Leaf-snowflake两种方案,前者基于数据库的自增主键,后者基于Snowflake算法。接下来介绍这两种方案的技术原理。 需要注意的是,Leaf和前几节介绍的几种技术方案非常相似,只是多了一些思考和优化,这也是我们在本节中重点着墨的部分。
4.5.1 Leaf-segment 方案Leaf-segment方案与4.4.2节介绍的批量缓存架构方案类似,只不过它没有依赖数据库的自增主键,而是在数据库中为每个业务场景都记录目前可用的唯一ID号段。具体的数据表设计如表4-1所示。
不同业务方的唯一ID需求用biz_tag字段区分,每个biz_tag的ID相互隔离。当某业务请求携带biz_tag访问Leaf服务时,数据库会通过执行如下语句生成唯一ID:
1234BEGINUPDATE table SET max_id = max_id + step WHERE b ...
基于数据库的自增主键也可以生成趋势递增的唯一 ID,且由于唯一ID不与时间戳关联,所以不会受到时钟回拨问题的影响。
4.4.1 分库分表架构数据库一般都支持设置自增主键的初始值和自增步长,以MySQL为例,自增主键的自增步长由auto_increment_increment变量表示,其默认值为1。MySQL可以使用SET命令设置这个变量值,比如SET @@auto_increment_increment=3会将自增步长设置为3。
在创建数据表时,MySQL可以为自增主键指定初始值。例如,如下建表语句会为test_primary_key表的自增主键设置初始值为10:
12345create table test_primary_key (id bigint unsigned not null auto_increment,col tinyint not null,primary key (id)) ENGINE=InnoDB AUTO_INCREMENT=10;
接下来向这个表中插入5条数据,然后看看主键的增长情况,如图4-11所示。
可以看到,第一条数据的主键为10,之后每个主键都 ...
时间戳是指计算机维护的从1970年1月1日开始到当前时间经过的秒数,并且随着时间的流逝而逐步递增。几乎所有的编程语言都仅需要一行代码,就可以轻而易举地得到当前时间戳,并支持毫秒精度,甚至是纳秒精度。时间戳自增的属性非常适合生成趋势递增的唯一ID。
4.3.1 正确使用时间戳时下最为普及的计算机普遍采用64位操作系统,对应的时间戳也是用64位表示的。在4.1.2节中已经明确了唯一ID也是64位的,这样不就意味着唯一ID正好可以用时间戳表示吗?这种做法是不可取的,原因很简单,在高并发场景下,同一时间有很多业务请求到达唯一ID生成器,如果用时间戳表示唯一ID,就会生成重复的ID。
对于基于时间戳的唯一ID,应该继续考虑高并发与分布式环境下的其他变量。例如:
服务实例:同一时间业务请求1和业务请求2分别从ID生成器服务实例A和服务实例B获取唯一 ID,为了防止生成重复的ID,在唯一ID上应该对服务实例的差别有所体现。
请求:同一时间业务请求1和业务请求2从LD生成器服务实例A获取唯一ID,在唯一ID上应该区分这两个请求。
话是没错,但是时间戳已经占用了唯一ID的全部空间,还怎么考虑其他变 ...