Osheep

时光不回头,当下最重要。

APP登录方案设计(二)

上篇说到APP登录和身份验证中涉及两个问题:1,怎么能最大程度避免泄露用户的密码;2,在登录后,app后端又怎么去验证和维持用户的登录状态呢。本文试讲第二个问题。

生成token

  1. 每次用户在注册或者登录时,验证密码通过以后,返回给用户一个token,APP缓存此token;
  2. 以后客户端每次发送请求的时候,都不用再带上密码了,直接带回token信息即可验证身份。
  3. 一般来说,token的生成一定要保持唯一,不然无法标明用户的唯一身份;
  4. token的生成策略,建议可以依赖自己的策略反解出userId,因为token一般是存储在缓存中的,当缓存挂掉以后,可以依赖于反解出的userId,使得服务暂时不至于不可用。常用的方法自然还是加盐和AES加密,而且这里的盐也不需要保存。

token安全性

  1. 每次请求都发送token,很明显的弊端是token容易被拦截,一旦token被拦截,用户的身份安全就会丧失;
  2. 有方法使token只传输一次的:只有用户第一次登陆的时候,下发一个token给客户端,以后每次请求都不再发送token,而使用加密算法来验证身份。
  3. 加密算法一般思路是:每次url请求的时候都带上用户自己的userId,同时对所有的key value参数,根据key的字母序排序组合成key1=value1&key2=value2的串,再把url请求的路径(类似/feed/1/comment)并入串中,最后再把token并入串中,然后求整个串的md5。请求的时候,添加一个参数 sign=md5签名结果。
  4. server收到请求之后,先用userId去找到此user的token,然后再使用此token做一遍与上面相同的加密,如果加密结果相同,则验证通过。如果缓存挂掉,则暂时不验证token和签名,保证服务暂时可用,然后尽快抢修缓存。
  5. 上述过程还有一个问题,如果一个串被别人拦截以后,可能会被多次用这个url访问,被重放攻击。为了防止重放攻击,所有的请求url中,都需要有一个参数 timestamp,标识此次请求产生的时间。服务端在收到请求以后,先判断timestamp是否在允许范围内,比如5min之内,如果不再则直接拒绝。
  6. 其实。。。。还有一个问题,APP在获取timestamp的时候,是依赖于手机时间的,如果用户调整了手机时间,或者手机时间不正确,那就可能发送过来的timestamp一直通不过server的验证。所以,timestamp方案,一般需要APP启动时候向服务器请求一个时间戳,然后在APP内部维护一个时钟,根据自己的时钟和获取到的时间戳来定义每次请求的timestamp。当然,timestamp方案也要求各个服务器的时钟要尽量同步。

token的进一步安全

  1. 到这里,身份验证是不是就绝对安全了呢? no。。。因为当用户在第一次登陆的时候,token回传的还是明文,这就是不安全的地方。那如果在这里保证token不明文呢?
  2. 【阅读原文】提供了一中方案,APP在登陆的时候,带过来自己随机生成的16位随机串,服务器在生成token以后,用这16位随机串加密token,然后再回传。APP在收到加密后的token以后,再使用相同的随机串解密,即可获得token;
  3. 聪明如你,肯定会想到,16位随机串如何保证安全传输?如果别人知道了你的算法,又嗅探到你的随机串,那你token同样是不安全啊?。。。
  4. 那该如何解决呢? 这个就是秘密了。

基本原则

  1. https。APP和server之间的连接,一定要使用https。
  2. 能不用明文传输的,尽量不要使用明文传输。
  3. token要有过期时间,不能无限制不过期,APP应该在token过期之前,拿着旧token去换新token,过程同拿密码换token。
《APP登录方案设计(二)》

不如假如
点赞