注册和登录几乎是所有产品的必备功能之一,本文作者以细节规则为例,讲解了注册、登录功能背后的设计原理,一起来看一下吧。
注册和登录功能几乎是所有产品的必备功能之一。对于用户,注册、登录后就可以生成唯一标识用户身份的信息,并基于此信息同步用户行为数据。对于平台或公司,用户注册时填写的有效信息可以有利于后期的精细化运营。
下面以细节规则为例讲解注册、登录功能背后的设计原理。
一、校验信息时的正则表达式
如图6-1所示,这是一款需要用户提供手机号和验证码进行注册、登录的App。在用户输入正确的手机号和验证码后,App服务器会校验该手机号是否已注册,若用户未注册就点击“登录”按钮,App会先帮用户完成注册,若用户已注册,则会成功登录。
再来对比两种情况。第一种情况,将手机断网并设为飞行模式。当手机号码输入框中没有任何内容时,发送验证码的按钮处于置灰状态且显示“请输入11位手机号码”的提示文案。当在手机号码输入框中输入了符合正常手机号码格式的手机号时,发送验证码的按钮处于可以点击的状态(颜色由灰变蓝)。
图6-1 登录页面手机号码校验示意图1
对照图6-2看看第二种情况。在手机号码输入框内输入了12位数字时,发送验证码的按钮再次处于置灰状态。将输入的数字调整为11位,并将首位数字改为2,即调整为不符合正常手机号码格式的情况,发送验证码的按钮也处于置灰状态。
图6-2 登录页面手机号校验示意图2
总结一下上面两种情况。在无网络情况下,App会对手机号码进行是否符合格式要求的校验。
那么如何校验呢?一般可以通过正则表达式。比如在上面的案例中,只要是1开头的11位数字就是符合要求的,可用正则表达式表示为 /^1[0-9]{10}$/。
二、怎么实现记住密码功能
为了方便用户下次登录,常见做法就是在用户第一次登录时,引导用户勾选类似记住密码的选项,当用户下次打开App时就可以直接登录App,如图6-3所示。
图6-3 登录时的记住密码功能
但登录时用户长期无须输入密码也存在一定的安全风险,部分平台在方便与安全之间做出了权衡,提供了多少天内免登录的选项。超出限制时间后,用户再打开App时依然需要输入密码。
在如图6-4所示的案例中,登录印象笔记网页版时,勾选了“30天内记住我”复选框,这样用户30天内均可自动登录印象笔记网页版,超出时间后才需要重新手动登录。
图6-4 登录时的“30天内记住我”功能
上述案例的核心技术原理分为两个方面,一个方面是如何记住密码,另一个方面是如何设置账号、密码的有效期。
1. 如何记住密码
账号和密码可以记录在本地。打开产品时,便将预先保存在本地的账号和密码取出,与服务器进行校验。这里的“本地”,对于Web产品来说就是在浏览器中,对于App来说则是在手机中。
常见的技术解决方案有哪些呢?
首先,是基于Cookie的方案。
Cookie是客户端向服务器发起请求后,服务器返回给客户端的信息之一,客户端会将Cookie保存下来并在后续接口中带上该信息,使服务器可以判断是哪个客户端发起的请求。
在自动登录场景下,用户首次登录后,账号和密码会被记录在Cookie中,后续登录时,客户端便从本地取出Cookie中的账号和密码发送给服务器验证,通过后登录成功,省去了用户手动重复输入账号和密码的过程。
在Web类型的产品中,则是利用localStorage来实现记住密码功能的。localStorage是HTML5标准中新加入的一种技术,该技术用于解决Cookie存储空间比较小的问题。与每条Cookie仅4Kb的容量大小相比,localStorage的容量大小一般会达到5Mb,具体容量大小在不同的浏览器中会存在差异。并且,保存在localStorage中的数据是永不过期的,除非进行了主动清空操作。
但把账号和密码信息保存在本地,存在账号密码被泄露及伪造的风险。所以,基于Token的方案便应运而生。大致过程与基于Cookie的方案类似,只是Token中无须保存账号和密码信息,从而提高了安全性。
2. 如何设置账号、密码的有效期
首先,依然是借助Cookie方案。在客户端向服务器发起请求之后,服务器给客户端返回Cookie时,直接设置好过期时间,一旦过期,客户端的Cookie信息就会被清除,后续登录则需要重新验证。
另外,就是借助Token方案。Token类似于Cookie,也可以设置过期时间。设定过程如下:首次登录时,客户端将账号和密码发送给服务器,服务器创建refresh token和token两个参数,将它们绑定,并设置不同的过期时间(一般可将token参数的过期时间设定得更早),后续登录只需带着Token即可校验。Token过期了以后,客户端就会向服务器重新申请Token,此时会先比对之前的refresh token,匹配后便生成新的token替换掉之前refresh token绑定的token,并将新的token返回给客户端,后续客户端发送请求时,带上新的token即可,于是用户的登录状态便是一直可用的,直到token和refresh token参数都过期后,用户才需要重新输入账号和密码。
三、单点登录
公司的产品数量不多时,用户注册账号登录,并结合记住密码功能,便可满足用户短期内均无须再次输入账号和密码的需求。
但公司产品数量增加后,依然会让用户感受到注册登录过程的烦琐。比如,腾讯、阿里这类大型公司旗下有众多产品,产品之间往往会产生关联,如果用户在使用其中某款产品时需要跳转到其他产品进行登录认证,一定会感到十分不便。对于产品设计者,也需要设计重复的登录认证逻辑。
解决这类问题的技术方案叫单点登录,英文全称是Single Sign On,缩写是SSO。这里有一个误区,因为很多产品经理一直以为,同一时间只允许一个账号在一台设备上登录的需求就是单点登录,但实际上单点登录是指产品中存在多套不同的系统,并且这些系统之间彼此是可信任的,只需让用户登录一次,后续便可直接登录产品中的任一系统。
目前市面上最主流的单点登录方案实现思路,要么是基于Cookie和Session自己搭建,要么是借助现成框架实现。
1. 直接基于Cookie与Session实现单点登录
一般公司的不同产品均位于同一个根域名下,但也不排除有些公司一条业务线或一个产品就占用一个单独的域名。举例说明,如果公司服务器域名为example.com,且存在两个系统对应的子域名为big.example.com及huge.example.com,在提供了登录功能的情况下,用户如果要打开这两个域名对应的系统页面,是需要分别登录的。那么怎样才能让用户在登录了其中一个系统后,打开另一个域名对应的系统时无须重复登录呢?
借助前面讲解过的Cookie知识,如果用户登录其中一个系统,在客户端本地记录下用户登录的Cookie信息,下次用户依然在同一端打开另一个系统登录,是不是可以将之前用户本地保存的Cookie信息拿过来直接用呢?遗憾的是,Cookie的使用不支持跨域,即不能直接拿Cookie中关于big.example.com域名的账号信息直接登录huge.example.com。那么,如何解决这个问题呢?好在设置Cookie时,除了可以设置当前域的信息,还可以设置对应的顶级域名,即example.com,在子域中又可以访问顶级域中的Cookie信息。
拿到登录账号信息还没完,还需要验证账号是否依然处于登录状态,此时就要借助Session来完成了。
用户在某个子域名登录后,服务器可在数据库中保存Session信息,其中就记录了登录状态。只要登录状态尚未结束,便可根据Cookie找到Session,保持之前的登录状态。具体如何根据Cookie找到Session呢?例如,用户在子域名big.example.com登录后,保存的是cookie1并生成对应的session1,然后在子域名huge.example.com登录,保存的是cookie2并生成对应的session2,两个独立的Session是无法知道彼此的登录状态的。为了解决这个问题,就需要借助Session共享技术。简单来讲,就是可将第一个子域名对应的系统与服务器会话时生成的Session共享给同一个根域名下的其他子域名使用,这样就可以解决有登录的Cookie信息,但没法确定登录状态,从而实现用户的免密登录。
2. 基于CAS方案实现单点登录
上面的方案已经能够解决不同产品归属同一顶级域名下情况的登录问题,但如果各个业务线域名都是独立的,那怎样实现单点登录呢?下面介绍市面上比较成熟的开源解决方案CAS。
在实现CAS这套方案时,除了需要提供正常的业务系统,还需要一个专门负责认证用户的系统,用于存储登录用户的标识。用户在登录其他系统时,借助已存储的标识进行验证,这时用户无须再次登录。在整套CAS方案中,认证系统被称为CAS Server,业务系统被称为CAS Client。
实现过程大致可以分为两个环节,一是初次登录,二是后续登录。
下面通过案例进行说明。假定某个集团公司叫小风科技集团,旗下的子公司分别叫中风科技发展有限公司和大风科技发展有限公司。中风科技发展有限公司主营业务是线上社交类电商,大风科技发展有限公司主营业务是线上医疗。两家公司原本独立运营,产品研发分离,域名也是独立申请的。因为战略方向上的调整,两家子公司的业务需要产生关联,需要进行产品整合,整合任务之一就是实现系统的单点登录。
先说初次登录。用户在使用子公司中风科技发展有限公司的产品时,之前登录时会直接请求服务器,改造为CAS模式后,则会变成先去请求CAS Server,若无法找到Cookie信息,则判定为初次登录,然后提示用户输入账号和密码进行登录。完成后,CAS Server便将登录信息(包括登录状态)一并写入服务器Session中,并记录下登录的Cookie信息。此外,它还会在登录成功后,生成一个叫作ST(Service Ticket)的内容,ST会在CAS Server和业务系统之间做来回的双向验证,双方确认无误后,首次登录就成功了。
再说后续登录。用户想要访问其他业务系统时,也会先将登录信息提交给CAS Server,待找到匹配的Cookie和Session信息,并经历ST的双向验证通过,就可以实现后续用户登录其他业务系统时,无须再次输入账号和密码便能直接登录的需求。
3. 基于OAuth方案实现单点登录
OAuth实际上是一种开放协议。通过这种协议,可以让第三方应用获取到用户在某一个平台存储的与个人信息相关的资源,并且在获取这些信息时,不需要用户提供账号和密码。
在讲解怎么样借助OAuth方案实现单点登录前,先讲讲OAuth协议的授权。
如图6-5所示,登录京东网页版时,选择使用微信等第三方账号授权登录,会展示让微信用户授权的二维码,在用户扫码同意授权以后,微信开放平台便会验证用户身份是否正确,如果正确,会生成一个临时的凭证给用户,用户再拿着这个临时凭证去微信开放平台换取access_token(注意这里的access_token是OAuth 2.0协议中客户端访问资源服务器时需要带上的令牌,有了这个令牌说明用户已经同意授权了)。到这一步后,基本上就已经完成了授权登录的过程。当然,后面还需要通过从微信获取到的用户信息来生成会话。
图6-5 京东网页版登录功能
在整个交互流程上,OAuth协议中涉及4个不同的角色,分别是resource owner(资源拥有者)、resource server(资源服务器)、client(客户端)、authorization server(授权服务器),不同的角色会起到不同的作用。资源拥有者代表用户信息归属于谁,在上面的案例中资源拥有者就是微信用户。资源服务器是存储授权后访问网页的用户信息的服务器,比如微信服务器。客户端即发起访问的客户端。授权服务器则是专门用于处理认证授权的服务器,在上面的案例中微信开放平台提供的认证服务器便充当了这个角色。上面的角色还可以继续简化,但至少需要保留客户端和授权服务器。
四、多终端设备的用户互踢
同一时间只允许一个账号在一台设备上登录,很多产品这样做是为了避免出现账号被他人使用但用户无法察觉的情况。针对这类需求,由于终端的差异,因此存在着不同的实现方式。
下面先来梳理场景。既然是端对端的访问过程,假定用户小风使用A账号在某个浏览器或App中登录,此时向服务器发起请求,服务器就会创建一个Session用于保持与客户端之间的会话状态。与此同时,服务器会基于客户端传来的一些参数(比如UUID、MAC地址等设备唯一标识)来生成Token,并将该Token与账号绑定,保存在服务器。另一个用户大风,这时也使用同样的账号A在不同的设备中登录,也同样会向服务器发起请求,服务器则会根据客户端提交的账号进行查询,发现Token已经存在,说明该账号还处于登录状态,但由于大风也向服务器发起了请求,所以为了确保大风能正常登录,便会生成一个新Token并将之前的Token信息删除。
在用户登录后,服务器还需要通知前面登录的用户被挤出登录的事实。
结合前面所学的网络请求相关知识,无论是移动端还是Web端,在与服务器交互的过程中,均为客户端发起请求,服务器响应并返回信息给客户端。采用这种方式意味着,虽然前面登录的用户明明已经被后面登录的用户“挤”了下去,但还是得通过某个特定的操作,向服务器发起请求,服务器查询到新用户使用同一个账号登录,才会为前面的用户注销登录。于是,就会出现在一段时间内,存在两个用户同时登录的状态。
因此,服务器如果能主动向客户端推送消息,就可以解决上面的问题,下面介绍两类解决方案。
1. 轮询与长轮询
轮询,可以被理解为在客户端,通过定时任务,定时向服务器发起请求,服务器收到请求后根据请求的信息进行响应。采用这种方式,有利有弊,优点是技术实现方便,缺点是会产生大量无效请求,加重网络负载,甚至还会造成服务器性能的浪费。
为了减少不必要的请求,便出现了长轮询。长轮询与轮询的不同之处在于,轮询时服务器收到客户端的请求后会立即响应,长轮询时服务器收到客户端的请求后不立即响应,而是会暂时保持发起请求后的连接状态,直到服务器得到客户端想要的结果后才通知客户端,从而减少向服务器发起请求的次数。
2. WebSocket
无论是轮询还是长轮询,都基于HTTP协议,该协议最大的缺点是无法做到服务器向客户端主动推送消息。为了克服这一缺点,下面将引出WebSocket方案。
WebSocket也是一种网络通信协议,但WebSocket协议与HTTP协议不同,其服务器与客户端之间可以双向互推消息。它最常见的应用场景便是即时通信、视频网站弹幕、在线协同文档等。
WebSocket方案的实现原理大致如下:客户端发起HTTP协议请求到服务器,并在请求头中附加Upgrade: WebSocket信息来表明将协议升级为WebSocket,服务器收到请求后返回允许客户端切换协议的响应信息 switching,此时双方便以WebSocket方式开启了通信管道,直到任意一方决定主动关闭。
五、离线登录是怎么一回事
离线登录指没有网络或服务器出现故障时,用户依然可以正常登录并使用产品。比如,对于随手记记账产品,用户在注册登录后,可记录自己的消费情况,进而形成好的理财习惯。为了兼顾用户体验及技术实现,一般会设计为在无网情况下,用户可以通过离线模式将数据记录在本地,待网络恢复后,再将数据上传至服务器。
想要实现离线登录,最好用户曾经采用联网的方式登录过产品,确保客户端本地保存了用户的Cookie信息,甚至还可以缓存一部分软件使用过程中的数据(比如刚才的记账信息),也就是通过本地数据持久化的方式进行实现,Cookie信息便是其中一种数据持久化方式。除此之外,将账号信息加密后以文件方式保存在本地也是可行的。
本文节选自作者新书《产品经理技术手册》,本书定位于让不懂技术的产品经理从产品经理的工作和思考方式切入了解应该掌握的技术原理。