【前端指南】session和token

session和token

cookie

  • http请求是无状态的,第一次和服务器连接并登陆成功后,第二次请求服务器仍然不知道当前请求的用户
  • cookie出现就是解决了这个问题
    • 第一次登陆后服务器返回一些数据cookie给浏览器,然后浏览器保存在本地
    • 当用户第二次返回请求时,就会把上次请求存储的cookie数据自动携带给服务器
    • 如果关闭浏览器cookie失效,则cookie就是保存在内存中
    • 如果关闭浏览器cookie不失效,则cookie保存在磁盘中
  • 但随着数据信息越来越多,每次请求的cookie也越来越大,对每个请求来说都是一个很大的负担

session

  • 与cookie作用有点类似,都是为了存储用户相关的信息,不同的是
    • cookie存储在本地浏览器,session存储在服务器
    • 存储在服务器的数据会更加安全,不容易被窃取,但是存储在服务器又有一定的弊端,会占用服务器的资源
工作机制
  1. 用户登录,server会为用户生成一个session,为其分配唯一的sessionId,是与某个用户绑定的,根据此sessionid可以查询到他到底是哪个用户,然后将此sessionid通过cookie传给浏览器
  2. 之后浏览器的每次请求只要在cookie里面带上sessionid = xxx这一个键值对即可,server根据sessionid找到它对应的用户后,把传过来的shangpinid保存到server中对应用户的信息即可
  • cookie存储在client,session保存在server,sessionid需要借助cookie的传递才有意义
session痛点
  • 上述情况能正常工作是因为我们假设了server是单机工作,但实际在生产上,为了保证高可用,一般服务期至少需要两台机器,通过负载均衡的方式来决定到底是该打到那台机器上
    • 客户端请求后,有负载均衡器,如Nginx来决定到底打到哪台机器
  • 假设登录请求打到了 A 机器,A 机器生成了 session 并在 cookie 里添加 sessionId 返回给了浏览器,那么问题来了:下次添加购物车时如果请求打到了 B 或者 C,由于 session 是在 A 机器生成的,此时的 B,C 是找不到 session 的,那么就会发生无法添加购物车的错误,就得重新登录了,此时请问该怎么办。主要有以下三种方式
    1. session复制
      • A请求生成的session后复制到其余机器,这样每台机器都有一份session,这样无论那台机器提供服务,session都能找到不会出现问题
      • 缺点
        1. 同样一份session保存了很多份,数据冗余
        2. 节点多的话,这样节点增多复制造成的性能消耗也会很大
    2. session粘连
      • 让每个客户端请求只打到一台机器上,比如浏览器登录请求打到A机器后,后续所有的添加处理请求也打到A机器上,Nginx的sticky模块可以支持这种方式,支持按ip或cookie粘连等,若ip粘连:
        • upstream tomcats {
            ip_hash;
             server 10.1.1.107:88;
             server 10.1.1.132:80;
          }
        • Nginx以事件驱动的方式编写,所以有非常好的性能,同时也是一个非常高效的反向代理、负载平衡服务器。在性能上,Nginx占用很少的系统资源,能支持更多的并发连接,达到更高的访问效率;在功能上,Nginx是优秀的代理服务器和负载均衡服务器;在安装配置上,Nginx安装简单、配置灵活
        • Nginx支持热部署,启动速度特别快,还可以在不间断服务的情况下对软件版本或配置进行升级,即使运行数月也无需重新启动
        • 在微服务的体系之下,Nginx正在被越来越多的项目采用作为网关来使用,配合Lua做限流、熔断等控制
      • 这样每个client请求到达Nginx后,只要他的ip不变,根据ip hash算出来的值会达到固定的机器上,也就不存在session找不到的问题了,当然不难看出这种方式缺点也很明显
        • 缺点:对应机器不能工作
    3. session共享
      • 将session保存在Redis,memcached等中间件中,请求到来时,各个机器去这些中间件中取一下session即可
      • 缺点
        • 每个请求都要去Redis取一下session,多了一次内部连接,消耗了一点性能,另外为了保证Redis的高可用性,必须做集群,让然对于大公司来说,Redis集群基本都会部署,所以该方案是大公司的首选

token

  • session的存储是需要空间的,session的传输一般都是通过cookie来传输,或url重写的方式
  • token在服务器时可以不用存储用户信息的,token传递的方式也不限于cookie传递,token也可以保存起来
  • 首先请求防输入自己的用户名,密码,然后server据此声称token,客户端拿到token后会保存到本地,之后想server请求是在请求头商带上此token
  • token 只存储在浏览器中,服务端却没有存储,这样的话我随便搞个 token 传给 server 也行?
    • server 会有一套校验机制,校验这个 token 是否合法
  • 怎么不像 session 那样根据 sessionId 找到 userid 呢,这样的话怎么知道是哪个用户?
    • token 本身携带 uid 信息
token组成部分
  1. header:指定了签名算法
  2. payload:指定用户id,过期时间等非敏感数据
  3. signature:签名,server根据header直到他改用哪种签名算法,再用密钥根据签名算法对head+payload生成签名
  • 以上,一个token就生成了
  • 当server收到浏览器传过来的token时,会首先取出token中的header+payload,根据密钥生成签名,然后再与token中的签名比较
    • 与token中的签名比对,如果成功则说明签名是合法的,即token是合法的
    • payload中存有userId
    • 对已拿到token后直接在payload中就可以获取到userId,避免了向session那样要从Redis去取的开销
token总结
  • 只要server保证密钥不泄露,那么生成的token就是安全的,因为如果伪造token的话在签名验证环节是无法通过的,就此即可判定token非法
  • 这种方式有效避免了token必须存在在server的弊端,实现了分布式存储
  • 注意
    • token一旦由server生成,他就是有效的,直到过期,无法让token失效
      • 除非在server为token设立一个黑名单,在教研token前先过一遍此黑名单,如果在黑名单里则此token失效
      • 但若向上述做法,就意味着黑名单必须保存在server,这又回到session模式
    • 所以一般做法是:当客户端登出要让token失效时,直接在本地转移token计科,下次登录重新生成token
    • token一般放在header的Authorization自定义头里面,不是放在cookie中,这主要是为了解决跨域不能共享cookie的问题

cookie与token的简单总结

cookie有哪些局限性?
  1. cookie跨站是不能共享的,这样的话要实现多应用多系统的单点登录SSO,使用cookie来做需要的话就很困难->要用比较复杂的trick来实现
    • SSO单点登录,是指在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统
    • 要用token来实现SSO会非常简单,只要在header中的authorize字段-或其他自定义,加上token即可完成所有跨域站点的认证
  2. 在移动端原生请求是没有cookie之说的,而sessionid依赖于cookie,sessionid就不能用cookie来传了
    • 如果使用token的话,由于它是随着header的authorize传过来的,就不存在此问题
      • 即token天生就支持移动平台,可扩展性好

token具有存储实现简单,扩展性好的特点

token的缺点?
  1. token太长
    • token是header,payload编码后的样式,一般要比sessionid长很多,很有可能超出cookie的大小限制(cookie一般都是有大小限制的,如4kb)
    • 若果在token中存储的信息越长,那么token本身也会很长
    • 这样的话,由于每次请求都会带上token,对请求来说是个不小的负担
  2. 不太安全
    • token存在浏览器的local storage里,这样会造成安全隐患,因为local storage这类本地存储是可以被JS直接读取的
    • 另外,token一旦生产就无法让其实小,必须要等其过期才行
    • 这样,如果服务端检测到了一个安全威胁也无法使相关的token失效

token更适合一次性的命令认证,设置一个比较短的有效期

一个误解

  • cookie相比token更不安全,比如CSRF攻击
CSRF攻击
  • 攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过得网站并运行一些操作,由于浏览器曾经认证过(cookie里带来sessionid等身份认证的信息),被访问的用户会认为是真正的用户操作而去运行
  • 在这里插入图片描述- CSRF攻击的根本原因在于:对于同样域名的每个请求来说,他的cookie都会被自动带上,这个是浏览器的机制决定的
  • 使用token确实会避免CSRF的问题,但由于token存在local storage,他会被JS,读取,从存储角度来看来不安全
    • 实际上防护CSRF攻击的正确方式是用CSRF token
  • 从存储角度来看都不安全,都有暴露风险,所以我们所说的安全更多是强调传输中的安全,可以用HTTPS协议来传输,这样的话请求头都能被加密,保证了传输中的安全

cookie和token比较本身就不合理,一个是存储方式,一个是验证方式

总结

  • session和token本质上是没有区别的,都是对用户身份的认证机制,知识他们实现的校验机制不同而已
    • 一个保存在server,通过在Redis等中间件获取来校验
    • 一个保存在client,通知签名校验的方式来验证
  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值