iOS怎么实现您的帐号在别的设备上登录,您被迫下线?

这个问题并非单纯的 iOS 开发问题,更多涉及到服务器接口设计。我在做乐涂鸦(NextDoodle)这个项目,也有类似的强制下线需求。我说说我的做法。我之前并非做服务器,NextDoodle 的后台服务器也是边学边做,我的做法可能不太正规,仅供参考,应该有更好的做法。我是 10 秒之内可以收到下线通知,平均时间为 5 秒,实时性不算高。

做这个后台服务器之前,我设定一个目标:服务器应该完全没有状态,所有的数据都存放在数据库当中。这样就可以随时重启更新服务器。服务器跟客户端的通信选取 https,通过 https 交换 Json 数据。

MySQL 数据库有个 User 表,User 表额外有两个字段,一个是 access_secret、一个是 last_login_secret。

用户通过 /user/login 接口登陆,登陆成功后,生成两个 uuid,分别给 access_secret 和 last_login_secret 赋值。向客户端返回 access_token 和 last_login_secret。其中 access_token 可以分解成三部分

用户 id

access_token 过期时间

md5

比如 userid 为 7,过期时间为 1482245339358(这个时间实际上是 Unix Timestamp, 精确到毫秒),access_secret 为 b09ea4db50ac3780e3fd1461829a0682(access_secret 为登陆后系统生成的 uuid, 将 uuid 去掉中划线,转成小写格式,就类似这样子了)。将三个字段连在一起,组成字符串

7:1482245339358:b09ea4db50ac3780e3fd1461829a0682

计算这串字符的 md5 得到 e8b725ae95985bfc4e356e4f79363377。最终的 access_token 为

7:1482245339358:e8b725ae95985bfc4e356e4f79363377

客户端登陆成功后,收到 access_token 和 last_login_secret,之后每个接口都带有 access_token 进行用户认证(这个 access_token 在请求时存放在 https 的 header 字段当中),而 last_login_secret 在客户端存储起来。

服务端用户认证的过程,就是将 access_token 分解成三部分。先判断 access_token 是否过期,再根据 userid 从数据库中取出用户数据,根据 access_secret 重新计算 md5,看看是否匹配,一旦不匹配,就返回表示 access_token 无效的错误码。

客户端收到 access_token 无效,就调用 /user/relogin 接口进行重新登陆,这个接口除了带有 /user/login 的全部参数,还带有 /user/login 返回的 last_login_secret。重登陆的过程,是取出数据表中用户的 last_login_secret,跟客户端传来的 last_login_secret 进行对比。当两者相同,就走登陆过程相同的流程。当两者不相等时,就返回表示重复登陆的错误码。客户端收到这个错误码,就弹出强制下线通知。

另外登陆成功之后,客户端会设立定时器,隔 10 秒左右,向服务器发请求,查询有没有更新的用户消息。这个时间间隔可以在服务端配置。

------------

描述完整个思路,现在看看会发生什么事情。假如用户在 A 设备登陆成功,收到 access_token 和 last_login_secret。之后定时器触发,每隔 10 秒,去获取用户通知。当 access_token 过期,就触发自动重登陆过程。自动重登陆成功后,access_token 和 last_login_secret 得到刷新,用户完全感觉不到有断线。

而当用户在 B 设备登陆成功后,数据库中的 access_secret 和 last_login_secret 得到更新。这时 A 设备去请求服务器时,access_token 不再匹配,触发重登陆过程,而 last_login_secret 也不再匹配,就返回重复登陆错误码。A 设备被强制下线。

因为拉取消息的时间间隔为 10 秒,这样在 10 秒之内,A 设备就会被强制下线。平均时间为 5 秒。而在这个时间内,客户端做网络请求,也就立即被强制下线。

-----------

其实可以将 access_secret 和 last_login_secret 合并成一个字段。但这时 access_secret 就会经过网络传输,感觉不太好。

后来 NextDoodle 出 iPhone 版本,需要支持 iPhone 和 iPad 可以同时登陆,而两台 iPad 不可以同时登陆。我的做法是延续原来思路,将 access_secret 拆分pad_access_secret、phone_access_secret,last_login_secret 拆分成 pad_last_login_secret、phone_last_login_secret。而 /user/login 和 /user/relogin 接口完全不用改变。通过 http 头部的User-Agent 字段,可以判断出当前设备是 iPhone 还是 iPad。

你可能感兴趣的:(iOS怎么实现您的帐号在别的设备上登录,您被迫下线?)