oauth1+jwt无状态登录策略分析

1.该版本的登录采用的是oauth1+jwt无状态登录策略
2.存在的问题
    1)同一用户可以在不同的地点同时登陆
    2)token的过期时间设置为1天,在一天内连续多次登陆,会生成多个不同的token,这些token都不会失效,都可以用来访问系统资源
    3)token 一旦派发出去,如果后端不增加其他逻辑的话,它在失效之前都是有效的    
3.解决办法(解决token失效问题)    
        1)将 token 存入内存数据库:
            将 token 存入 DB 中,redis 内存数据库在这里是是不错的选择。
          如果需要让某个 token 失效就直接从 redis 中删除这个 token 即可。但是,这样会导致每次使用 token 发送请求都要先从 DB 中查询 token 是否存在的步骤,
          而且违背了 JWT 的无状态原则。
        
        2)黑名单机制:
            和上面的方式类似,使用内存数据库比如 redis 维护一个黑名单,如果想让某个 token 失效的话就直接将这个 token 加入到 黑名单 即可。
          然后,每次使用 token 进行请求的话都会先判断这个 token 是否存在于黑名单中。  
        
        3)修改密钥 (Secret) : 
            我们为每个用户都创建一个专属密钥,如果我们想让某个 token 失效,我们直接修改对应用户的密钥即可。
            但是,这样相比于前两种引入内存数据库带来了危害更大,比如:1:如果服务是分布式的,则每次发出新的 token 时都必须在多台机器同步密钥。
            为此,你需要将必须将机密存储在数据库或其他外部服务中,这样和 Session 认证就没太大区别了。
            2:如果用户同时在两个浏览器打开系统,或者在手机端也打开了系统,如果它从一个地方将账号退出,那么其他地方都要重新进行登录,这是不可取的。
        
        4)保持令牌的有效期限短并经常轮换:
            很简单的一种方式。但是,会导致用户登录状态不会被持久记录,而且需要用户经常登录。    
4.token 的续签问题
    token 有效期一般都建议设置的不太长,那么 token 过期后如何认证,如何实现动态刷新 token,避免用户经常需要重新登录?

    我们先来看看在 Session 认证中一般的做法:假如 session 的有效期30分钟,如果 30 分钟内用户有访问,就把 session 有效期被延长30分钟。

    1)类似于 Session 认证中的做法:
        这种方案满足于大部分场景。假设服务端给的 token 有效期设置为30分钟,服务端每次进行校验时,
    如果发现 token 的有效期马上快过期了,服务端就重新生成 token 给客户端。客户端每次请求都检查新旧token,如果不一致,则更新本地的token。
    这种做法的问题是仅仅在快过期的时候请求才会更新 token ,对客户端不是很友好。
    
    2)每次请求都返回新 token :这种方案的的思路很简单,但是,很明显,开销会比较大。
    
    3)token 有效期设置到半夜 :这种方案是一种折衷的方案,保证了大部分用户白天可以正常登录,适用于对安全性要求不高的系统。
    
    4)用户登录返回两个 token :第一个是 acessToken ,它的过期时间 token 本身的过期时间比如半个小时,另外一个是 refreshToken 它的过期时间更长一点比如为1天。
    客户端登录后,将 accessToken和refreshToken 保存在本地,每次访问将 accessToken 传给服务端。服务端校验 accessToken 的有效性,
    如果过期的话,就将 refreshToken 传给服务端。如果有效,服务端就生成新的 accessToken 给客户端。否则,客户端就重新登录即可。
    该方案的不足是:
        1:需要客户端来配合;
        2:用户注销的时候需要同时保证两个 token 都无效;
        3:重新请求获取 token 的过程中会有短暂 token 不可用的情况(可以通过在客户端设置定时器,当accessToken 快过期的时候,
          提前去通过 refreshToken 获取新的accessToken)。    

5.优缺点
    1)好处(那Token相对于Cookie的好处):
        支持跨域访问: Cookie是不允许垮域访问的,token支持
        
        无状态: token无状态,session有状态的
        
        去耦: 不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成,只要在 你的API被调用的时候, 你可以进行Token生成调用即可.
        
        更适用于移动应用: Cookie不支持手机端访问的
        
        基于标准化: 
            你的API可以采用标准化的 JSON Web Token (JWT). 这个标准已经存在 多个后端库(.NET, Ruby, Java,Python, PHP)
            和多家公司的支持(如: Firebase,Google, Microsoft)
    2)缺点:
         安全性:
            由于jwt的payload是使用base64编码的,并没有加密,因此jwt中不能存储敏感数据。而session的信息是存在服务端的,相对来说更安全
         性能:
            jwt太长。由于是无状态使用JWT,所有的数据都被放到JWT里,如果还要进行一些数据交换,那载荷会更大,经过编码之后导致jwt非常长,cookie的限制大小一般是4k,
            cookie很可能放不下,所以jwt一般放在local storage里面。并且用户在系统中的每一次http请求都会把jwt携带在Header里面,http请求的Header可能比Body还要大。
            而sessionId只是很短的一个字符串,因此使用jwt的http请求比使用session的开销大得多。
        一次性:
            无状态是jwt的特点,但也导致了这个问题,jwt是一次性的。想修改里面的内容,就必须签发一个新的jwt。
        无法废弃:
            通过上面jwt的验证机制可以看出来,一旦签发一个jwt,在到期之前就会始终有效,无法中途废弃。例如你在payload中存储了一些信息,当信息需要更新时,
            则重新签发一个jwt,但是由于旧的jwt还没过期,拿着这个旧的jwt依旧可以登录,那登录后服务端从jwt中拿到的信息就是过时的。
            为了解决这个问题,我们就需要在服务端部署额外的逻辑,例如设置一个黑名单,一旦签发了新的jwt,那么旧的就加入黑名单(比如存到redis里面),
            避免被再次使用。
        续签:
            如果你使用jwt做会话管理,传统的cookie续签方案一般都是框架自带的,session有效期30分钟,30分钟内如果有访问,有效期被刷新至30分钟。
            一样的道理,要改变jwt的有效时间,就要签发新的jwt。最简单的一种方式是每次请求刷新jwt,即每个http请求都返回一个新的jwt。
            这个方法不仅暴力不优雅,而且每次请求都要做jwt的加密解密,会带来性能问题。另一种方法是在redis中单独为每个jwt设置过期时间,每次访问时刷新jwt的过期时间。

6.适合使用jwt的场景
    1)有效期短
    2)只希望被使用一次
    
    比如,用户注册后发一封邮件让其激活账户,通常邮件中需要有一个链接,这个链接需要具备以下的特性:能够标识用户,该链接具有时效性(通常只允许几小时之内激活),
    不能被篡改以激活其他可能的账户,一次性的。这种场景就适合使用jwt。
    
    你要是正在使用 jwt 访问一个接口,这个时候你的同事跑过来把你的 jwt 抄走了,这种泄露................

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值