赞
踩
今天的鸡汤有点毒:
你必须敢爱敢恨,才会发现你的爱恨别人真的不在乎
本来想写的挺多,看了很多别人优秀的文章后,突然感觉,我写的可能是个渣渣~but,我还是要写的,毕竟有的时候自己写过的东西比较容易回忆起来。
最近看了很多关于cookie、session和token的资料,在此总结一下吧,留着以后想起来的时候看看。有一些个人理解,慎重~~
我废话是真的多,哎……
这一切都要源于客户端和服务器端之间的爱恨情仇吧。
最初的WEB端,页面就是个辅助的作用。一般就是个form表单,action指向一个http接口。提交表单,发起请求,接受响应,仅此而已。(感觉这句话真的说过好多次~)
每个http请求是相互独立的,毫无关联的。这就是人家说的http是一个无状态协议的意思。干净利落,运行快速。棒棒!
但是随着交互式Web应用的兴起,前端作用越来越重要,逻辑越来越复杂。这种无状态协议已经不能满足我们的大多数需求,比如现在市场上绝大多数的网站都是有登录系统的,登录后看到的页面都是我们自己的信息,以及一些个性化定制的页面展示。比如说某宝,我们登录后,购物车是我们之前添加的物品,给我们推荐的全都是我们感兴趣的东西,所以我们操作任何一步的时候服务器必定是知道当前用户的信息的。
所以现在的需求是需要服务器记住用户的登录信息。
想要实现这样的需求,就需要让服务器知道每个http请求是哪个用户发送的,这样才能根据不同的用户返回不同的信息。但是总不能每发送一次http请求都携带着用户名和密码,这很奇怪,很啰嗦,也很不安全。
有问题就要解决嘛,所以有大牛提出了解决方案:用户登录成功时,服务器给这个用户分配一个会话标识sessionId保存在数据库,就是一个唯一的随机字符串,并将该sessionId返回给浏览器,浏览器再次发送http请求时,携带上这个参数,服务器端对该用户的sessionId进行验证,这样就能确定用的登录信息了。用户退出时,注销这个sessionId就可以了。
我们采用了这个方案。并将这个sessionId的保存在cookie中。所以你可以理解为cookie其实是一个用于保存sessionId的文本文件。
Cookie最早是网景公司的前雇员Lou Montulli在1993年3月的发明。
Cookie是一个很具象的概念。看图:
我们打开F12的开发者工具,如果当前的网站是存在Cookie信息的话,在这里是可以看到的。
所以,cookie其实就是用来存储数据的。未设置超时时间的cookie保存在临时存储器中,浏览器关闭后,会自动清除;设置了超时时间的cookie,会将这些数据保存在本地的一个文本文件中。
Cookie是一个保存在客户机中的简单的文本文件, 这个文件与特定的 Web 文档关联在一起,保存了该客户机访问这个Web 文档时的信息,当客户机再次访问这个 Web 文档时这些信息可供该文档使用。是一段不超过4KB的小型文本数据,由键值对和其它几个用于控制Cookie有效期、安全性、使用范围的可选属性组成。
Cookie的属性:
所以关于cookie,在我的理解上大概是这么回事:
在用户填写登录信息发起登录请求时,服务器端生成该用户唯一的sessionId之类的唯一标识,将其与该用户的登录信息,一起保存在数据库中(现在大多保存在临时数据库redis之类的)。
然后将sessionId之类的标识数据放在响应头中,命名为set-cookie,返回给浏览器。
浏览器将这些信息保存在cookie临时文件中。
然后再次向服务器发送请求的时候,浏览器会自动将cookie中的信息放在请求头中一同发送到服务器,服务器会根据cookie中的信息来获取当前用户的登录信息。
这样就解决了http无状态协议的问题啦。
cookie验证流程:
打开F12,可以在响应头(Response Headers)中发现返回了set-cookie:
再次发送请求时,会发现请求头(Request Headers)中自动携带了cookie的参数。
所谓cookie,大概就是这么回事。
接下来说下Cookie的特点:
了解了cookie之后,咱们来点实际的,如何在前端拿到cookie的值呢?(虽然一般情况下,前端不会去操作cookie的值。)
JavaScript 可以使用 document.cookie 属性来创建 、读取、及删除 cookie。
document.cookie = "sessionid=88888"; // 注:给cookie新增个属性
console.log(document.cookie); // 获取cookie的值,当前cookie值为(sessionid=88888)
document.cookie = "pp=123"; // 重新给cookie赋值
console.log(document.cookie); // 再次获取cookie的值
// 删除cookie,设置它的超时时间为一个过去的时间,比如我设置为这个Thu, 01 Jan 1970 00:00:00 GMT
// 然后咱们删除之前添加的pp属性
document.cookie = 'pp=;expires=Thu, 01 Jan 1970 00:00:00 GMT';
console.log(document.cookie); // 再次获取cookie的值
然后咱们来看些执行结果:
从这个现象中,我们可以发现一些好玩的东西,记下来哈,知识点!
通过上边的了解,我们可以发现Cookie还是存在一些弊端的:
所以一种新的验证方式出现了——token。
token和Cookie的目的是一样的,都是为了验证用户的登录信息和状态。
token的实现思路,用我的理解大概是这个样子的:
用户填写登录信息之后呢,发送给服务器,进行验证,服务器验证用户登录成功后,将用户名通过一系列加密,转码,各种算法后,生成一个秘钥,也叫签名。然后将用户名和秘钥做成一个token返回给客户端。大概是这么个感觉:token: {‘zhangsan’,‘6bf7532j34h2jbkgjk%lk2390fj3%2’}。
客户端拿到这个token后呢,每次发送http请求的时候,都会携带上这个token一起发送至服务器,服务器端拿到token后,将前边的用户名按照那套加密转码的算法,再生成一个秘钥,如果新生成的秘钥和发送来的秘钥统一,则证明该用户登录状态是正确的。然后就可以继续下边的操作了。
这个过程,完全的略过了服务器的存储问题。棒呆!
当然有人说,那玩意这套加密算法泄露了呢,用户信息不就不安全了吗?拜托,人家又不傻,加密算法是每隔一段时间会变的。等你破解出来了,人家都换算法了。(如果你非说有高级黑客,那我只能说人家直接去攻击服务器不好吗,偷个token去看页面至于吗。)
一顿比比叨,不知道大家听明白没,没有的话,咱们再站在学术的角度说下,咳咳:
token验证流程:
token的优点:
session,字面上的意思,就是会话。一次会话,就是一次浏览器和服务器之间的对话,所以其实你可以理解为一个http请求。上回书说道,http协议是无状态的,所以咱们在cookie中保存sessionid,可以保证用户的登录状态,才得以让多次会话之间产生关联。
但是呢,我们也知道cookie是存在弊端的,比如cookie存储在客户端的,且本身存储大小有限,最可怕的是对用户可见,可随意修改,安全性不好。所以,服务器觉得还是自己安全,于是产生了session,就是将这些信息存储在服务器端。
服务器中的session机制,即用户登录的时候,会随机生成一个唯一的32位的session_id,来唯一标识一个会话(说白了就是确定是否为同一用户),然后作为set-coolie的值传递给客户端。
sessionid生成后,服务器端肯定是要将该sessionid对应的session信息保存下来的,不然下次怎么验证呢。由于会话结束后,这些session信息肯定是要删掉的,所以一般会将这个session信息写入临时文件中,所以下次http携带着sessionid发起请求的时候,服务器需要找到对应的临时文件,来获取这个用户的登录信息。
这样大家应该就比较理解session机制了。因为session机制主要是在服务器端,而且现在存储在redis中居多,redis拥有着更快的读取和写入速度,因为redis是直接操纵内存数据的,肯定是要比文件的形式快很多,还可以更好的设置好过期时间。之前也说过session过多时,也会影响session的读取速度,设置redis 的主从同步,可以快速的同步session到各台web服务器,比文件存储更加快速。
1、cookie、token 和 session的区别是什么?
其实完全理解了三者个概念后,看这个问题就很奇怪了,cookie和session不应该是同伙么,怎么还有区别呢? 而且面试官真的很爱问这种问题……人家又不可能瞎问是吧。
所以我觉得他问的session和cookie的区别,应该是后端有无session机制的区别,即把用户所有信息都存在cookie中和存储在session中的区别,哈哈,那就很明显了:
然后咱们再总结一个session和cookie变成同伙之后和token的区别吧:
首先呢,两者的目的都是一样的,只不过实现方式不同。
2、为什么token不会被CSRF攻击?
CSRF(Cross-site request forgery)跨站请求伪造:是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
简单的说,就是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。
比如,你在你的浏览器中执行了一个给zhang的转账的操作,转账的url是“http://xxxx?name=12&account=100000&for=zhang”。这时因为网站已经认证了你的信息,所以cookie中存储着你的sessionid。
然后你没有执行退出操作,即当前的sessionid还是有效的时候,你在当前浏览器中访问了另一个网站。这个新的网站中,攻击者加入了一句代码“<img src=“http://xxxx?name=12&account=100000&for=bad”/>”。
因为图片肯定是会自动加载的,那么这个http请求就会被执行,而你的浏览器的cookie中保存的sessionid还是有效的,所以浏览器会自动携带cookie中的sessionid,导致你自动给bad这个人转账了。
所以cookie容易被CSRF攻击,但是token不会,因为token不会被浏览器自动携带,所以在其它网站中如果没有手动设置token,那么就不会被CSRF攻击。
3、XSS攻击?
上边咱们说过cookie中有些值,需要设置httponly属性,目的是为了防止XSS攻击,那咱们就说一下XSS攻击吧!
XSS攻击——跨站脚本攻击:通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。
意思就是代码毕竟是代码,只要语法正确,它就会执行,它并不关心这个代码是谁写的。
比如攻击者在你的目标服务器注入可执行脚本: <script>alert("你个傻子!)</script>,页面就会弹出这个alert ,如果将script标签的src设置为恶意的js文件,那么这个网站受到的攻击会是非常大的。
所以,cookie中关于用户信息的属性需要设置httpOnly为true,否则攻击者通过document.cookie就能轻易的拿到用户的sessionid,那产生的损失将是巨大的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。