作者:刘魏威
通讯录同步,这里仅指手机客户端与服务端之间的单向同步,不讨论syncML等同步协议。本篇文章是开发通讯录数据同步和好友匹配过程中的问题总结。
同步方式的选择关系到开发成本、服务稳定性及用户体验,因此需要慎重考虑。
明显的好处是客户端开发简单,每次都直接上传全量数据,其他均交给服务端处理。然而客户端每次上传时,数据量可能比较大,网络传输会存在瓶颈,同时服务端处理时间因数据量的大小而不确定,服务很难承诺稳定,最终导致用户体验差。
假设我们以全量同步的方式去实现,服务端具体会面临哪些问题呢?下面来仔细分析下:
客户端每次只上传变更的数据,只有第一次需要全量上传。好处是只有第一次可能体验差,但后续的请求都能快速处理,服务端稳定性相对有所提高。
增量同步需要考虑脏数据的问题,可能由于某种原因同步失败,客户端丢失数据,服务端能够识别并要求客户端重新全量上传。
不论是全量同步还是增量同步,对于服务端来说开发量是一样的,每次上传,业务逻辑基本可以当做全量同步来处理。同步的接口可以开两个,方便做故障隔离及限流。传输数据格式定义上,尽量使用字符串拼接,不要用json,保证传输的数据量尽可能小。
用户通讯录是基于设备的,即每个设备只会有一个通讯录。但对于一个app来说,在同一个设备可以使用多个app账号登陆的,因此服务端存储的通讯录是基于设备还是账号,需要考虑下。如果基于设备,设备id可以伪造,看起来不太安全。基于账号,那么同一个设备的通讯录可能在服务端被存储多次,数据重复,而且用户切换账号,需要全量上传,处理的逻辑较多。从用户体验的角度来看,基于设备比基于账号更合理。
由于通讯录是属于比较私人的信息,一旦泄露后果不堪设想,因此通讯录数据需要有较高的安全等级。
数据安全主要从两个角度来看:
这两者在开发过程中都需要保证。
数据加密算法主要有两类,对称加密和非对称加密,下面来分析如何做出选择。
比较常见的加密算法,服务端和客户端同时存储一份相同的密钥,只要密钥不暴露,即可认为数据是安全的。当前考拉实名认证,身份证信息加密传输就是使用的此种算法。这么做有什么缺点呢?
服务端存储私钥,客户端存储公钥,不存在密钥泄漏的风险。但RSA算法对明文长度有要求,不能超过公钥长度,如果超过,需要对明文进行分段加密。
在实现过程中,可以综合两种算法的优缺点,实现一套相对安全的加解密方案:
1、客户端随机生成固定长度的对称密钥,使用此密钥来加密通讯录数据
2、使用RSA公钥来加密对称密钥,数据上传时,同此上传对称加密后的数据和非对称加密后的密钥
3、服务端收到数据,先用RSA私钥解密对称密钥,再用对称密钥解密通讯录数据
最终由于开发时间的限制,选了目前正在使用的AES加密算法来传输,客户端不用进行额外的开发,服务端也不用针对环境来提供不同的公钥。
通讯录数据存储使用的是通用AES加解密服务(特地针对社区提供批量加解密接口)。使用通用AES加解密服务时需要注意,由于系统会定期更换密钥,相同的明文在不同的时间会生成不同的密文。这一点会导致什么呢?如果你用加密后的数据来做业务逻辑判断,比如需要判断一个手机号在业务表(里面存储的手机号已经加密)里是否存在,先使用通用加密服务进行加密,然后去业务表里面查询,这个时候很可能查不到!因此,需要十分注意,加密后的数据,仅能用来解密,不能作于其他任何用途。如果需要以手机号作为业务唯一性用途,可以使用固定算法对手机号生成一个不可逆的特征码,查询时以特征码为准。
通讯录上传完后,客户端有查询通讯录匹配到的好友并展示联系人姓名的需求。如何防止联系人数据泄密?最主要的风险在于通讯录是基于设备id的,而设备id可以伪造,因此需要识别查询请求是否真正来自通讯录所属设备。可以设计一个请求签名:
request_sign = AES_Encrypt(last_data_sign,device_id,timestamp)
last_data_sign指客户端最后一次同步数据签名,存储在客户端本地,每次同步完数据,客户端需要保存下来。last_data_sign加device_id可以防止设备伪造,timestamp可以防止请求被拦截后重放。
接收到客户端上传的数据,先做解密验证,数据有效则存储并生成异步任务,任务落db成功即返回,保证接口响应时间。如果是全量同步,由于上传完客户端需要马上查询,为了能保证查到数据,服务端同步前两页的数据,其他批次异步处理。异步任务因机器重启、网络故障等原因处理失败,需要有定时重试机制兜底。
由于存在重试机制,通讯录的增改删均需要实现幂等处理。
通讯录上传->匹配好友->获取匹配结果,这个流程是一个整体,用户无操作上的感知,要么全部成功,要么全部失败。但实际上无法百分百保证流程中每一步都成功,为防止某一步失败导致功能不正常,客户端、服务端都需要有容错处理机制。
网易云大礼包:https://www.163yun.com/gift
本文来自网易实践者社区,经作者刘魏威授权发布