Cookie、Session、Token

无论是web应用还是原生app应用,只要涉及网络连接,基本就离不开登录注册,我们注册完成后登录,这个状态就被保持下来了,我们下次打开app,应用就已经处于登录状态了,不需要我们重复登录,非常人性化,感觉服务器好像会“记得”我们每一个人一样,“记得”你来过,就不再要求你登录了。但其实计算机在这方面是很傻的,他不是自发“记得”我们的,这篇文章就来聊聊登录状态的保持是怎么实现的。

HTTP协议

http协议是无状态的,什么是无状态呢?就是说这一次请求和上一次请求是没有任何关系的,互不认识的,没有关联的。无状态就意味着每个请求之间的不会直接地相互影响,对于每个请求,同样的请求参数就会得到同样的结果。
假如我们想要把www.zhihu.com/login.htmlwww.zhihu.com/index.html关联起来,必须使用某些手段和工具

HTTP如何保存登录状态?

当我第一次调用用户名密码验证接口的时候,我需要输入账号、密码,服务器收到请求之后,就会根据账号去数据库取你的密码和你输入的密码进行比对,然后返回一个“密码正确”或“密码错误”。而问题在于当我第二次访问这个接口的时候,服务器依旧会执行他的职能:收到我发送的账号和密码,然后去数据库取数据进行比对后返回比对结果,对于服务器来说,每个请求不过是做了类似1+1是否等于2的判断然后返回结果而已。

我想要服务器能够记住我已经调用过一次登录接口并且以及成功了这个状态,应该怎么办?

我们可以很自然的想到,服务器不知道我们登录过的原因是因为没有记下来,要保持登录状态,只要让服务器记下来就可以了。我们可以在服务器专门设置一个存储,每次只要我验证账号和密码成功,就在这个存储里面存下A登录成功,这样我们服务器就记得A登录过了。

现在服务器已经知道A登录过了,但是这就够了吗?不够,因为HTTP请求并不会自动标明“这是A发起的请求”,所以我们还要做点工作让服务器能知道“这是A发起的请求”,然后服务器才好去存储下来的登录状态里面找A登录成功”这个标志。怎么做?我们可以在调用请求的时候把自己的用户名加进请求的参数中,比如Get请求的URl参数、Post请求的请求Body中,这样服务器就可以根据我们的用户名判断我们有没有登录过了。

这样我们就初步的把登录状态保存了下来,其实这样的验证非常粗糙,所以基于这个思想,产生了下面的技术。

Cookie

什么是Cookie

Cookie就是存储在客户端的一小段数据,它可以存在硬盘中(永久Cookie),也可以存在内存中(临时Cookie)

Cookie字段

在这里插入图片描述

  • Name:Cookie名。
  • Value:Cookie值。
  • Domian:Cookie来自哪个域名。
  • Path:路径,表示Cookie作用在哪些地方,/表示对整个树有效。
  • Expires/Max-Age:设置了Cookie的过期时间。如果该字段不存在,则表示Cookie在浏览器退出时被丢弃,这种Cookie被称为非持续Cookie(nonpersistent cookie);如果针对了Cookie设置了时间和日期,这种Cookie被称作持续Cookie(persistent cookie),它将被保存至过期为止。为了从客户端删除一个Cookie,服务器只要将此Cookie再发送一次,但是这个Cookie的过期时间被设置为一个过去的时间,这就是我们会看到有些Cookie的过期时间是过去的原因。
  • Secure:指示浏览器只使用安全传输连接的服务器返回Cookie,应用在对于安全要求较高的地方,比如网上交易等。

Cookie、Session是如何保持登录状态的

什么是Session

Session是指服务器为某个会话开启的一段独特的存储空间(会话是指一个终端用户与交互系统进行通讯的过程,比如说我先登录,再查看我的邮箱内容,这个过程就是一个会话),一个Session用唯一的SessionId对应一段存储空间。

Cookie和Session的关系

看了上面的Cookie和Session的解释,以及Cookie和Session的使用,就可以发现它们两个其实完全不冲突,甚至这两者是需要相互配合的,因为Cookie是在客户端的存储,Session是在服务端的存储,Session的存储需要SessionId来一一对应,这样才不会出现xxx获得了A的登录状态然后用JabinGP的钱买东西这样的情况,SessionId则需要通过Cookie保存在用户客户端中,客户端通过保存在Cookie的SessionId来标识自己,表明“我就是A”。
在这里插入图片描述
PS

  • cookie只是实现session的其中一种方案。虽然是最常用的,但并不是唯一的方法。禁用cookie后还有其他方法存储,比如放在url中
  • 现在大多都是Session + Cookie,但是只用session不用cookie,或是只用cookie,不用session在理论上都可以保持会话状态。可是实际中因为多种原因,一般不会单独使用
  • 用session只需要在客户端保存一个id,实际上大量数据都是保存在服务端。如果全部用cookie,数据量大的时候客户端是没有那么多空间的。
  • 如果只用cookie不用session,那么账户信息全部保存在客户端,一旦被劫持,全部信息都会泄露。并且客户端数据量变大,网络传输的数据量也会变大
    简而言之, session 有如用户信息档案表, 里面包含了用户的认证信息和登录状态等信息. 而 cookie 就是用户通行证

Token

token 也称作令牌,由uid+time+sign[+固定参数]
token 的认证方式类似于临时的证书签名, 并且是一种服务端无状态的认证方式, 非常适合于 REST API 的场景. 所谓无状态就是服务端并不会保存身份认证相关的数据。

存放
token在客户端一般存放于localStorage或sessionStorage中。在服务器一般存于数据库中

token认证流程

token 的认证流程与cookie很相似

用户登录,成功后服务器返回Token给客户端。
客户端收到数据后保存在客户端
客户端再次访问服务器,将token放入headers中
服务器端采用filter过滤器校验。校验成功则返回请求数据,校验失败则返回错误码

Token可以抵抗CSRF,Cookie+Session不行

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

总结

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

参考1
参考2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值