App 长登录思考与实现
4、双 token 方式
虽说一直在改进,但 token、设备指纹毕竟是从终端取过来的,中间人同时做替换,也有可能造成身份替换。业界逐渐出现双 token 的模式,以及对 token、设备指纹按需存储的技术。先说双 token。
(1)access token 与 refresh token
双 token 理念主要来源于 OAuth2.0。OAuth1.0 的 access token 获取之后,就可以存到数据库里长期使用。OAuth2.0 为了增强安全性,access token 的有效期大大缩短,通常只有几个小时,也可以按需申请增加到几十天,总之是可配置的。因此,OAuth2.0 增加了一个可选项 refresh token,access token 用于请求 api 的功能不变,refresh token 并不能用于请求 api,它是用来在 access token 过期后刷新 access token 的一个标记。OAuth1.0 中用户的登录状态是一直存在的,OAuth2.0 中用户的登录状态需要通过不断刷新来维持的。
图 RFC6749 定义的 Oauth2.0 中 token 使用的基本流程
用户授权之后,获取到一个 access token 和一个 refresh token,还有一个是 session key,这个是国内大多数开放平台自己添加的一个标记,可以让用户使用 http 来调用 api,如果没有它,用户只能通过 https 来调用 api.session key 的生命周期和 access token 是相同的。我们把这三个值存到一个队列的数据库中。
然后在每天固定的时间,遍历这个数据库表,取出它的 access token 和 session key,然后用他们去请求 api。如果发现他们已经过期,我们就需要利用 refresh token 去重新刷新,获取新的 access token 和 session key,然后利用他们去请求 api,如果请求的时候提示 refresh token 也已经过期,那么这时候用户的登录状态就会过期,这说明这个用户至少 2 各月没有在此应用活跃了,这个活跃不光指用户自己在使用应用,也包括应用自动调用用户 api 的行为。
access token 有效期可以设置的很短,比如 1 天,refresh token 有效期可以设置的长一些,比如 7 天。例如,在 spring-oauth-server 中,默认 access token 有效时间为 12 小时,默认 refresh token 有效时间为 30 天。每次刷新 refresh token 的时候都会返回一个新的 token 值,如果在 refresh token 有效期范围内有使用 App,则 App 用户会一直处于登录状态。
双 token 的优势:
accessToken 的存在,保证了登录态的正常验证,因其过期时间的短暂也保证了帐号的安全性;
refreshToekn 的存在,保证了用户(即使是非活跃用户)无需在短时间内进行反复的登录操作来保证登录态的有效性,同时也保证了活跃用户的登录态可以一直存续而不需要进行重新登录,其反复刷新也防止某些不怀好意的人窃取用户的 refreshToken。
双 token 工作流程:
首先进行正常的登录操作,在后台服务器验证账号密码成功之后返回 2 个 token:accessToken 和 refreshToken;
发送请求时,先验证 accessToken 是否存在、是否在有效期内,没有问题则正常返回请求结果;
如果 accessToken 验证失败,则验证 refreshToken。此时如果 refreshToken 有效则返回请求结果和新的 accessToken 和新的 refreshToken;失效则提示用户重新登录。
(2)设备号/设备指纹
上文也提到,refresh token 的过期时间一般会比较长,为了安全起见(比如丢了手机),这类 token 一定要与设备进行绑定,通过设备号/设备指纹做设备与 token(也就是账号)的关联。
终端有“原罪”,除非使用持续更新的密码白盒、指令替换、虚拟化、专用芯片等高强度的终端管控技术,否则都不应在客户端本地完成敏感数据的计算和存储。因此,本段 3.2 中所采用的、在终端计算设备号/设备指纹再进行传输的方式是强烈不建议使用的。建议使用的方式,是在终端侧收集若干设备信息,直接进行传输,算法和结果都在后台存储,每次传输的都只是设备信息。双 token 工作流程进一步完善如下:
首先进行正常的登录操作,发送账号、口令、终端设备信息,后台收到 request 之后,验证账号及口令,通过后计算设备信息形成并存储设备号/设备指纹,返回 2 个 token:accessToken 和 refreshToken。账号、设备号/设备指纹、accesstoken、refreshtoken 四个值进行关联。
发送请求时,先验证 accessToken 是否存在、是否在有效期内,没有问题则正常返回请求结果;如果不在有效期内,则根据请求中一并带上的终端设备信息,到后台计算得到设备号/设备指纹,与该账号对应的后台存储的设备号/设备指纹值进行对比,不一致则直接提示用户重新登录。一致的话则验证 refreshtoken。
验证 refreshToken 有效,则返回请求结果和新的 accessToken 和新的 refreshToken;失效则提示用户重新登录。
上述流程对于设备号/设备指纹的处理,还可以进一步延伸,满足风控需求:
可以采用对用户可见的方式,并允许用户对当前登录态设备进行操作。比如在安全中心里检验了身份之后,可以让用户看到哪些设备上有 token,即哪些设备处于登录态,或曾经登录过,如果手机丢了,或者出现了用户不认识的设备,结合最近一次登录时间,允许用户移除丢失手机的 token,强制下线。
灰/黑名单:出现登录异常时,比如同一设备上登录了好多账号,则可以通过预警、打标等方式,对设备、账号进行风险关注。例如,将需要关注的设备、账号放到灰名单,做分析使用;根据实际情况,比如出现大量转账操作时,再放到黑名单中。
三、总结
OAuth 用于第三方认证,所以需要严格控制给第三方认证权限的时间,但时间太短了重新登录又会影响用户体验,在这种情况下,出现了双 token 的模式。
另外一点,因为移动互联网技术的普及,使得确认人、账号、移动终端设备三者关系的问题,演变成安全最重要的问题之一。这个问题在用户安装 App 的最初就出现了,并一直伴随着用户的登录、使用、退出、再登录、丢手机、换手机、双机等全生命周期的过程而存在。设备指纹、生物识别等技术是当前解决这一问题的主要技术手段。未来可能还有更多的技术方式出现,攻防相长。
App 长登录的问题,绝对不只是登录的问题。
版权声明: 本文为 InfoQ 作者【石君】的原创文章。
原文链接:【http://xie.infoq.cn/article/5f907c8c6a36d3dfab236b4c7】。文章转载请联系作者。
评论