zoukankan      html  css  js  c++  java
  • 一文理清Session,Cookie和Token

    前言

    之前看了不少同类型的文章,对于Cookie和Session真是众说纷纭,有的人说先有Cookie才有Session,也有的人说现有Session再有Cookie。我也说说我的理解,希望对大家有所帮助。
    注:需要读者对于Cookie/Session/Token有基本的了解。

    Cookie和Session

    说这俩之前,先说http,它是一个无状态协议。
    怎么理解呢?就是说连续的两次请求之间是没有任何关联的。这样的好处是快速,坏处是想要把同个域名下的两个页面关联起来,必须使用某些手段和工具。
    这就引出了我们要说的Cookie和Session。
    让我们用文字+图片了解一下客户端访问服务器的流程:
    • 首先,客户端会发送一个http请求到服务器端;
    • 服务器端接受客户端请求后,建立一个Session,并发送一个http响应到客户端,这个响应头,其中就包含Set-Cookie头部。该头部包含了SessionId;
    • 在客户端发起的第二次请求,假如服务器给了Set-Cookie,浏览器会自动在请求头中添加Cookie;
    • 服务器接收请求,分解Cookie,验证信息,核对成功后返回response给客户端。

    这里有几点要注意的:
    • Cookie只是实现Session的其中一种方案。虽然是最常用的,但并不是唯一的方法。禁用Cookie后还有其他方法存储,比如放在url中;
    • 单一使用Session不用Cookie,或者反过来只用Cookie不用Session,在理论上都可以保持会话状态,只是实际操作中因为多种原因,大多都是Session + Cookie;
    • 用Session只需要在客户端保存一个id,实际上大量数据都是保存在服务器端。如果全部用Cookie,数据量大的时候客户端是没有那么多空间的;
    • 如果只用Cookie不用Session,那么账户信息全部保存在客户端,一旦被劫持,全部信息都会泄露。并且客户端数据量变大,网络传输的数据量也会变大。

    简单总结,就是Session 有点像用户信息档案表, 里面包含了用户的认证信息和登录状态等信息,而 Cookie 就是用户通行证。

    Token

    Token 也称作令牌,由uid+time+sign(+固定参数)组成:
    • uid: 用户唯一身份标识
    • time: 当前时间的时间戳
    • sign: 签名, 使用 hash/encrypt 压缩成定长的十六进制字符串,以防止第三方恶意拼接
    • 固定参数(可选): 将一些常用的固定参数加入到 Token 中是为了避免重复查库
    Token 的认证方式类似于临时的证书签名, 并且是一种服务器端无状态的认证方式, 非常适合于 REST API 的场景. 所谓无状态就是服务器端并不会保存身份认证相关的数据。
    Token在客户端一般存放于LocalStorage,Cookie,或SessionStorage中。在服务器一般存于数据库中。

    Token认证流程

    Token 的认证流程与Cookie很接近
    • 用户登录,成功后服务器返回Token给客户端;
    • 客户端收到数据后保存在客户端;
    • 客户端再次访问服务器,将Token放入Headers中;
    • 服务器端采用filter过滤器校验。校验成功则返回请求数据,校验失败则返回错误码。

    Cookie,Session和Token的区别

    Token可以抵抗CSRF攻击,Cookie+Session不行
    我们假设一个场景:
    用户正在登陆银行网页,同时登陆了攻击者Tom的网页;
    银行网页未对CSRF攻击进行防护;
    Tom在网页放了一个表单,该表单提交src为http://www.bank.com/api/transfer,body为count=1000&to=Tom。
    如果用的是Session+Cookie,用户打开网页的时候就已经被Tom转走卡里的钱了。因为form 发起的post请求并不受到浏览器同源策略的限制,因此可以任意地使用其他域的 Cookie 向其他域发送 post 请求,形成 CSRF 攻击。在post请求的瞬间,Cookie会被浏览器自动添加到请求头中。
    但Token不同,Token是开发者为了防范CSRF而特别设计的令牌,浏览器不会自动添加到Headers里,攻击者也无法访问用户的Token,所以提交的表单无法通过服务器过滤,也就无法形成攻击。

    分布式情况下的Session和Token

    我们已经知道Session是有状态的,一般存于服务器内存或硬盘中,当服务器采用分布式或集群时,Session就会面对负载均衡问题。
    • 负载均衡多服务器的情况,不好确认当前用户是否登录,因为多服务器不共享Session。这个问题也可以将Session存在一个服务器中来解决,但是就不能完全达到负载均衡的效果。有办法解决但是挺麻烦的。
    而Token是无状态的,Token字符串里就保存了所有的用户信息
    • 客户端登陆传递信息给服务器端,服务器端收到后把用户信息加密(Token)传给客户端,客户端将Token存放于LocalStroage等容器中。客户端每次访问都传递Token,服务器端解密Token,就知道这个用户是谁了。通过cpu加解密,服务器端就不需要存储Session占用存储空间,就很好的解决负载均衡多服务器的问题了。
    注:这个方法叫做JWT(Json Web Token)。

    总结

    • Cookie类似一个令牌,装有SessionId,存储在客户端,浏览器通常会自动添加。
    • Session存储于服务器,可以理解为一个状态列表,拥有一个唯一识别符号SessionId,通常存放于Cookie中。服务器收到Cookie后解析出SessionId,再去Session列表中查找,才能找到相应Session。同时Session依赖Cookie。
    • Token可以说是一个无状态的令牌,需要开发者手动添加。用户信息被加密到Token字符串中,服务器收到Token后解密就可知道是哪个用户。
    • JWT只是一个跨域认证的方案。

    撰写
    Eolinker:致力于API全生命周期开发管理的国产流行API工具。
    参考文章
    Cookie、Session、Token那点事儿
    cookie,token验证的区别
    有了cookie为什么需要session
    彻底弄懂session,cookie,token
    CSRF Token的设计是否有其必要性
    cookie,token,session三者的问题和解决方案
    负载均衡集群中的session解决方案
    JWT介绍
    Json Web Token 入门教程

  • 相关阅读:
    37-Data Volume 之 bind mount
    Python encode和decode
    Python迭代器,生成器(iterator,generator)详解
    Python递归函数
    pandas.DataFrame的pivot()和unstack()实现行转列
    Python XML解析之DOM
    Python XML解析之ElementTree
    Oracle 12c用户和安全管理
    Oracle 12c RAC 静默安装文档
    Oracle 12c RAC 安装文档
  • 原文地址:https://www.cnblogs.com/dc20181010/p/15247735.html
Copyright © 2011-2022 走看看