Cookie、Session与Token

更新日期: 2019-06-09阅读: 2.8k标签: 存储

Cookie

Cookie是一个http请求首部,当服务端响应头上标记着setCookie时,可以设置此cookie到当前域名下。浏览器端会将此cookie以kv的形式存储到本地文件中


Session

session实际上是一种概念,表示每次会话服务器存储的用户信息

实现:

常见的手段是使用cookie来实现session。以java为例,客户端首次请求服务端后(例如登录),服务端通过setCookie 设置jsessionid (不设置cookie超时时间,浏览器对于不设置cookie超时间的cookie会在浏览器标签页关闭时自动清空这些cookie)。服务端存储这个sessionid。当客户端第二次请求服务端时,浏览器会自动将属于该域名下的cookie通过http请求首部带到后端服务器中,后端服务器跟本地存储的sessionid进行验证来比对是否是正确用户。
既然session是个概念,那么也肯定有其他的实现方式。还有一种需要前端配合的实现方式是通过页面的url中携带session信息。来实现客户端和服务端session之间的传递,不过比较麻烦与过时,这里不详细介绍。

缺点:

  1. 每次认证用户发起请求时,服务器需要去创建一个记录来存储信息。当越来越多的用户发请求时,内存的开销也会不断增加。
  2. 当用户过多时,在服务端的内存中存储的大量session信息会严重影响内存,不方便扩展。比方说当你打算用两台电脑存储session时,session的同步就很不方便。也可以使用单独的服务器使用redis来存放session信息。但是万一这一台数据库服务器宕机后,让所有正在登陆的用户重新登陆当然会让用户很不爽。


Token:

token是一种身份验证的机制,初始时客户端携带用户信息访问服务器(比如说登录),服务端采用一定的加密策略生成一个字符串(token)返回给客户端,客户端保存token的信息,并在接下来请求的过程中将token信息用户信息通过httpHeader来发送给服务端。客户端跟据相同的加密算法对用户信息进行比对,生成新的token和用户发过来的token进行比对,来判断是否是正确且过期的用户。
这个时候我们就可以考虑到其实用服务器的session也可以实现类似于token的功能,那么为什么一定要用token。我在网上找到一个值得信服的理由是:如果是开发api接口,前后端分离,最好使用token,为什么这么说呢,因为session+cookies是基于web的。但是针对 api接口,可能会考虑到移动端,app是没有cookies和session的。

实现:

  1. 使用cookie来实现。使用cookie实现的话就和session差不多。这里不多加赘述。
  2. 使用其他的httpHeader来实现。这就需要前端的一定配合。完整方案如下:

    • 随便设定一个响应头与请求头,比方说userToken,Authorization,前端访问后台登录接口获取到token后,将token存储在 Cookie 里或者 Local Storage中。
    • 在前端的请求ajax加一个过滤,再向后端发送请求时,先再beforSend函数中设置这个请求头。后端收到请求后也先检测规定请求头中是否携带了token并且验证token是否过期(实际开发中还是比较少用这种情况,因为直接设置一个过期时间比较长的token即可,当发现过期是就直接返回token过期即可)
    • 在前端的响应中加一个过滤,检测后端发回的token是否更新,如果更新则更新持久化的token信息(目的是token续期)

通过上面的这一套流程我们能发现使用token还是很麻烦的。需要大量的前端配合,所以这种方案真的很适合前后端分离的项目(由于前后端分离,那么前端大概率是SPA单页面应用,这种应用基本都会在ajax中加过滤,方便对统一的ajax返回的错误信息进行统一处理等)
对于服务端来说,有统一的标准来实现token,叫JWT(JSON WEB TOKEN)有兴趣深入了解的话可以看下面的参考文章

token的优势

  1. 方便横向拓展 比方说我们有不用语言构建的服务,比方说java node php等等。那么我们如何做到统一登录呢,这个时候就需要统一的验证机制。
  2. 由于不再依赖cookie,所以不再有CSRF问题
  3. 支持移动设备

有状态Token

实际开发过程中,我们实际上还是会把token存入服务器,这样就跟web中session基本没什么区别。因为token中内容还是比较长的,每次客户端访问服务器都带着这么长的信息,并且每次在服务器还要重新计算进行比对还是比较耗费时间和流量的。
所以我们还是要用有状态token,我们可以想象下传统session的实现:客户端频繁访问服务器只携带session_id,然后服务器通过session_id去session中查找对应的存储信息。有状态token也是使用这个逻辑:在用户第一次登陆成功后,服务器生成token,因为token比较长,遂将其存在了服务器,然后返回客户端一个加密的tokenid,客户端每次通过这个加密的tokenid访问服务器,原理就跟session_id的流程是一样的了。
我们知道服务器的session是存储在内存中的,为了高效。同理我们将token信息也存储在服务器的内存,通用的解决方案是存储到redis中,我们知道redis的存储是基于内存的。速度会比数据库快一些,同时redis是可以设置数据的有校时间的,假如有效期为30天,在插入数据时,就可以设置该条数据的有效期为30天,30天后,redis就会自动删除该数据。那么30天后,用户携带tokenid来访问服务器,服务器去redis中查询不到信息,代表验证失败。(当搭建集群后redis显得尤为重要,分布式session就是通过redis解决的)。


感悟

技术只是手段,不同的使用场景用不同的技术。

链接: https://fly63.com/article/detial/4130

js中cookie操作总结:cookie设置,读取,删除,判断是否存在

有时也用其复数形式 Cookies,指某些网站为了辨别用户身份,JavaScript对cookie的相关操作,设置cookie,读取cookie,删除cookie,判断cookie是否存在.......

HTML5新方法:前端存储localStorage的使用总汇

在HTML5中有一个localStorage的新特性,它主要用于本地存储使用,目的是为了解决了cookie存储空间小的问题。本文将讲解:localStorage特点、localStorage的兼容、localStorage的使用等

Token ,Cookie和Session的区别

在做接口测试时,经常会碰到请求参数为token的类型,但是可能大部分测试人员对token,cookie,session的区别还是一知半解

介绍web开发中实现会话跟踪的常用技术方法

由于http是无状态的协议,这种特性严重阻碍了客户端与服务器进行动态交互,为了弥补http的不足,目前实现会话跟踪的常用技术方法:cookie、session、url重写、隐藏input、ip地址。

关于网页本地存储的一些思考

localStorage 与 sessionStorage具体适用于什么样的业务场景?如何维护本地储存?如何进行版本控制?碰到禁止本地缓存的情况下怎么解决这个问题?

JS中原始值和引用值的储存方式

在ECMAscript中,变量可以存放两种类型的值,即原始值和引用值。原始变量及他们的值储存在栈中,当把一个原始变量传递给另一个原始变量时,是把一个栈房间的东西复制到另一个栈房间,且这两个原始变量互不影响。

前端数据保存_使用js开发数据库

前端很多时候还是需要保存一些数据的,这里的保存指的是长久的保存。以前的思想是把数据保存在cookie中,或者将key保存在cookie中,将其他数据保存在服务器上。想要一种能够长久的保存在本地的数据,类似数据库或者类似web sql。

Cookie防篡改机制_cookie怎么防止被篡改/伪造

因为Cookie是存储在客户端,用户可以随意修改。所以存在一定的安全隐患,服务器为每个Cookie项生成签名。如果用户篡改Cookie,则与签名无法对应上。以此,来判断数据是否被篡改。

在前后端分离的项目中,ajax跨域请求怎样附带cookie

后台保存用户信息通常使用的session和cookie结合的方法,而在前端的实际情况中,跨域产生的ajax是无法携带cookie信息的,这样导致了session和cookie的用户信息储存模式受到影响,该怎样去解决这样一个问题呢

localStorage设置过期时间

我们都知道localStorage不主动删除,永远不会销毁,那么如何设置localStorage的过期时间呢?使用场景: 1.利用本地数据,减少网络传输 ,2.弱网络环境下,高延迟,低带宽,尽量把数据本地化

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!