JavaScript系列—cookie,session,token等

前言

之前整理过cookie,session,token,但发现还是云里雾里,今天读了几篇经典的文章,彻底的弄清楚这个东西。

首先我们需要知道,这三个东西的为了解决什么问题

HTTP是一种无状态的协议,而服务器端的业务必须是要有状态的, 为了分辨链接是谁发起的,需自己去解决这个问题。不然有些情况下即使是同一个网站每打开一个页面或者 APP 每次进入也都要登录一下。

而 Session 、 Cookie、Token、JWT 等就是为解决这个问题而提出来的几个机制。

先来欣赏下面的鉴权流程图(图片来自百度)

 根据上图可以看到,从用户请求发起,到服务端完成操作,流程颇多,但是HTTP无状态,我们如何才能详细记录这些操作过程并加以严格的权限判断控制,接下来就开始今天的主题!

1.cookie

Cookie 诞生的最初目的是为了存储 web中的状态信息,方便服务器端使用。比如判断用户是否是第一次访问网站等问题。

cookie是保存在本地终端的数据。cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。

  1. cookie 是客户端技术,程序把每个用户的数据以 cookie 的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。

  2. cookie 的处理:

  • 服务器向客户端发送 cookie

  • 浏览器将 cookie 保存

  • 之后每次 http 请求浏览器都会将 cookie 发送给服务器端

关于cookie的相关概念可以参考《Javascript高级程序设计》里面的章节,这里不做过多的描述

2.session

session从字面上讲,就是会话。这个就类似你和一个人交谈,你怎么知道当时和你交谈的是张三而不是李四呢?对方肯定有某种特征(长相等)表明他是张三;
session也是类似的道理,服务器要知道当前请求发给自己的是谁。为了做这种区分,服务器就是要给每个客户端分配不同的"身份标识",然后客户端每次向服务器发请求的时候,都带上这个”身份标识“,服务器就知道这个请求来自与谁了。
至于客户端怎么保存这个”身份标识“,可以有很多方式,对于浏览器客户端,大家都采用cookie的方式。

理解一 

  1. 浏览器第一次访问服务器,服务器会创建一个 session,并生成一个 sessionId

  2. 将 sessionid 及对应的 session 分别作为 key 和 value 保存到缓存中,也可以持久化到数据库中

  3. 服务器再把 sessionid,以 cookie 的形式发送给客户端

  4. 浏览器下次再访问时,会直接带着 cookie 中的 sessionid。然后服务器根据 sessionid 找到对应的 session 进行匹配

理解二

 

 

存在的问题—扩展性不好

单机当然没问题, 如果是服务器集群, 或者是跨域的服务导向架构, 这就要求session数据共享,每台服务器都能够读取session。

举例来说, A网站和B网站是同一家公司的关联服务。现在要求,用户只要在其中一个网站登录,再访问另一个网站就会自动登录,请问怎么实现?这个问题就是如何实现单点登录的问题

  1. Nginx ip_hash 策略,服务端使用 Nginx 代理,每个请求按访问 IP 的 hash 分配,这样来自同一 IP 固定访问一个后台服务器,避免了在服务器 A 创建 Session,第二次分发到服务器 B 的现象。

  2. Session复制:任何一个服务器上的 Session 发生改变(增删改),该节点会把这个 Session 的所有内容序列化,然后广播给所有其它节点。

  1. 共享Session:将Session Id 集中存储到一个地方,所有的机器都来访问这个地方的数据。这种方案的优点是架构清晰,缺点是工程量比较大。另外,持久层万一挂了,就会单点失败;

 

另一种方案是服务器索性不保存session数据了,所有数据就保存在客户端,每次请求都发回服务器。这种方案就是接下来要介绍的基于Token的验证;

3.token

先来思考一下

于是有人就一直在思考, 我为什么要保存这可恶的session呢, 只让每个客户端去保存该多好?

可是如果不保存这些session id ,  怎么验证客户端发给我的session id 的确是我生成的呢?  如果不去验证,我们都不知道他们是不是合法登录的用户, 那些不怀好意的家伙们就可以伪造session id , 为所欲为了。

嗯,对了,关键点就是验证 !

比如说, 小F已经登录了系统, 我给他发一个令牌(token), 里边包含了小F的 user id, 下一次小F 再次通过Http 请求访问我的时候, 把这个token 通过Http header 带过来不就可以了。

不过这和session id没有本质区别啊, 任何人都可以可以伪造,  所以我得想点儿办法, 让别人伪造不了。

那就对数据做一个签名吧, 比如说我用HMAC-SHA256 算法,加上一个只有我才知道的密钥,  对数据做一个签名, 把这个签名和数据一起作为token ,   由于密钥别人不知道, 就无法伪造token了。

这个token 我不保存,  当小F把这个token 给我发过来的时候,我再用同样的HMAC-SHA256 算法和同样的密钥,对数据再计算一次签名, 和token 中的签名做个比较, 如果相同, 我就知道小F已经登录过了,并且可以直接取到小F的user id ,  如果不相同, 数据部分肯定被人篡改过, 我就告诉发送者: 对不起,没有认证。

Token 中的数据是明文保存的(虽然我会用Base64做下编码, 但那不是加密), 还是可以被别人看到的, 所以我不能在其中保存像密码这样的敏感信息。

当然, 如果一个人的token 被别人偷走了, 那我也没办法, 我也会认为小偷就是合法用户, 这其实和一个人的session id 被别人偷走是一样的。

这样一来, 我就不保存session id 了, 我只是生成token , 然后验证token ,  我用我的CPU计算时间获取了我的session 存储空间 !

解除了session id这个负担,  可以说是无事一身轻, 我的机器集群现在可以轻松地做水平扩展, 用户访问量增大, 直接加机器就行。   这种无状态的感觉实在是太好了!

https://mp.weixin.qq.com/s/VMry3HwJNf0AX57EM1h4Kw(上面内容这篇文章,写的很好)

下来我们来详细的介绍一下token

token的意思是“令牌”,是用户身份的验证方式,最简单的token组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,由token的前几位+盐以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接token请求服务器)。还可以把不变的参数也放进token,避免多次查库。

4.区别

Cookie和Session的区别

 

  1. 存储位置不同: cookie数据存放在客户的浏览器上,session数据放在服务器上

  2. 隐私策略不同:cookie不是很安全, 别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session

  3. session会在一定时间内保存在服务器上。当访问增多,就会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie

  4. 存储大小不同: 单个cookie保存的数据不能超过4k, 很多浏览器都限制一个站点最多保存20个cookie

一般建议: 将登陆信息等重要信息存放为session, 其他信息如果需要保留,可以放在cookie中

Token和Session的区别

Session是一种HTTP储存机制, 为无状态的HTTP提供持久机制;
Token就是令牌, 比如你授权(登录)一个程序时,它就是个依据,判断你是否已经授权该软件;

Session和Token并不矛盾,作为身份认证Token安全性比Session好,因为每一个请求都有签名还能防止监听以及重放攻击,而Session就必须依赖链路层来保障通讯安全了。如上所说,如果你需要实现有状态的回话,仍然可以增加Session来在服务端保存一些状态。

总结

cookie,session,Token没有绝对的好与坏之分,只要还是要结合实际的业务场景和需求来决定采用哪种方式来管理回话,当然也可以三种都用。

 

下面看一个很形象的比喻

比喻:

Cookie:

发给顾客一张卡片,上面记录着消费的数量,一般还有个有效期限。每次消费时,如果顾客出示这张卡片,则此次消费就会与以前或以后的消费相联系起来。这种做法就是在客户端保持状态。 【卡上记录所有信息,而店家只认卡不认人。】

Session:

发给顾客一张会员卡,除了卡号之外什么信息也不纪录,每次消费时,如果顾客出示该卡片,则店员在店里的纪录本上找到这个卡号对应的纪录添加一些消费信息。这种做法就是在服务器端保持状态。 【只记用户ID,而ID的详细记录放在店家的数据库里;每次凭ID检索服务器的记录。】

【 这里用一个形象的比喻来解释session的工作方式。假设Web Server是一个商场的存包处,HTTP Request是一个顾客,第一次来到存包处,管理员把顾客的物品存放在某一个柜子里面(这个柜子就相当于Session),然后把一个号码牌交给这个顾客,作为取包凭证(这个号码牌就是Session ID)。顾客(HTTP Request)下一次来的时候,就要把号码牌(Session ID)交给存包处(Web Server)的管理员。管理员根据号码牌(Session ID)找到相应的柜子(Session),根据顾客(HTTP Request)的请求,Web Server可以取出、更换、添加柜子(Session)中的物品,Web Server也可以让顾客(HTTP Request)的号码牌和号码牌对应的柜子(Session)失效。顾客(HTTP Request)的忘性很大,管理员在顾客回去的时候(HTTP Response)都要重新提醒顾客记住自己的号码牌(Session ID)。这样,顾客(HTTP Request)下次来的时候,就又带着号码牌回来了。 我们可以看到,Session ID实际上是在客户端和服务端之间通过HTTP Request和HTTP Response传来传去的。】

 

为什么登陆后,只要不关闭浏览器,session就能一直存在?当然session的数据是保存在服务器上的,但服务器是怎么识别这些数据都是谁的呢?

答 案是sessionid,每一个浏览者都唯一的sessionid,这就很好的区分了不同浏览者的不同session了.

sessionid是怎么产生 的?

应该是第一次访问服务器的时候随即生成的.假如是111,然后他的登陆信息是true,服务器就知道sessionid为111已经登陆了,这些信息 都存在了服务器上了.

但当浏览者继续操作的时候,也就是打开该系统的另一个页面的时候sessionid怎么办?如何传递?

打开另一个页面的时候其实相当 于重新访问系统,如果没有特殊的处理机制,系统会再次重新分配一个sessionid的,这样的话就失去意义了~!所以sessionid在第一次访问后 应该存在了客户端.

能寸哪呢?

当然,只能寸在cookie中了,这就是为什么关闭cookie,session就失去作用了 

找到这么个例子来描述cookie session的关系再恰当不过了 
一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠,然而一次性消费5杯咖啡的机会微乎其微,这时就需要某种方式来纪录某位顾客的消费数量。想象一下其实也无外乎下面的几种方案: 
1、该店的店员很厉害,能记住每位顾客的消费数量,只要顾客一走进咖啡店,店员就知道该怎么对待了。这种做法就是协议本身支持状态。 
2、发给顾客一张卡片,上面记录着消费的数量,一般还有个有效期限。每次消费时,如果顾客出示这张卡片,则此次消费就会与以前或以后的消费相联系起来。这种做法就是在客户端保持状态。 
3、发给顾客一张会员卡,除了卡号之外什么信息也不纪录,每次消费时,如果顾客出示该卡片,则店员在店里的纪录本上找到这个卡号对应的纪录添加一些消费信息。这种做法就是在服务器端保持状态。 
第 一种情况暂时不考虑.看第二种情况,卡片无疑就是cookie了,所有的数据如果都存在卡片上是不安全的,也是容易遗失的(卡片被修改了?卡片遗失了?这 都是有可能的).所以才用了第三种情况.客户除了个会员号再什么信息也没有,这是最安全的,但这个会员号必须是客户自己知道的!也就是cookie中必须 存储的.

 

个人理解:

cookie会较长时间留在客户端硬盘里,session是在会话期内有效。Used by browser to keep the state

session可由cookie carry给服务器,就是session搭cookie的车。

session可用于hold住购物车等。

最后的最后,如何是在还是忘记了的话,请看下面两篇博文

https://mp.weixin.qq.com/s/SY-5ETSjwSB28o95NIsxGw

 https://mp.weixin.qq.com/s/FcRmDuKU9zoAkNmiZJ-oYw

------------------------------------------------------------------------------华丽分割线----------------------------------------------------------------------------

1.什么是cookie

cookie : 存储数据,当用户访问了某个网站(网页)的时候,我们就可以通过cookie来像访问者电脑上存储数据

  1.不同的浏览器存放的cookie位置不一样,也是不能通用的

  2.cookie的存储是以域名形式进行区分的

  3.cookie的数据可以设置名字的

  4.一个域名下存放的cookie的个数是有限制的,不同的浏览器存放的个数不一样

  5.每个cookie存放的内容大小也是有限制的,不同的浏览器存放大小不一样

  我们通过document.cookie来获取当前网站下的cookie的时候,得到的字符串形式的值,他包含了当前网站下所有的cookie。他会把所有的cookie通过一个分号+空格的形式串联起来

  如果我们想长时间存放一个cookie。需要在设置这个cookie的时候同时给他设置一个过期的时间

  cookie默认是临时存储的,当浏览器关闭进程的时候自动销毁

 下面是一个例子,注意在chrome上面会失效,火狐可以。

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>无标题文档</title>
<script>
window.onload = function() {
	
	var oUsername = document.getElementById('username');
	var oLogin = document.getElementById('login');
	var oDel = document.getElementById('del');
	
	if ( getCookie('username') ) {
		oUsername.value = getCookie('username');
	}
	
	oLogin.onclick = function() {
		
		alert('登陆成功');
		setCookie('username', oUsername.value, 5);
		
	}
	
	oDel.onclick = function() {
		removeCookie('username');
		oUsername.value = '';
	}
	
}

function setCookie(key, value, t) {
	var oDate = new Date();
	oDate.setDate( oDate.getDate() + t );
	document.cookie = key + '=' + value + ';expires=' + oDate.toGMTString();
}

function getCookie(key) {
	var arr1 = document.cookie.split('; ');
	for (var i=0; i<arr1.length; i++) {
		var arr2 = arr1[i].split('=');
		if ( arr2[0] == key ) {
			return decodeURI(arr2[1]);
		}
	}
}

function removeCookie(key) {
	setCookie(key, '', -1);
}
</script>
</head>

<body>
	<input type="text" id="username" />
    <input type="button" value="登陆" id="login" />
    <input type="button" value="删除" id="del" />
</body>
</html>

这里有个小插曲,一直都是困惑我的地方,今天终于豁然开朗。

当我点击上面的用户名输入框的时候,就会出现一些我以前登录过的用户名和密码,注意这个是浏览器的行为。当你点击登录的时候,浏览器就会出现这个,当你点击了保存,那么下次下拉就会出现啦。和现在说的cookie没有关系哦。

 2.cookie,seesion,token

关于这三个的区别,可以看简书上面这一篇文章写得很好https://www.jianshu.com/p/43c3003ac957。下面简单的来回答一下

1.token就是令牌,比如你授权(登录)一个程序时,他就是个依据,判断你是否已经授权该软件;

2.cookie就是写在客户端的一个txt文件,里面包括你登录信息之类的,这样你下次在登录某个网站,就会自动调用cookie自动登录用户名;session和cookie差不多,只是session是写在服务器端的文件,也需要在客户端写入cookie文件,但是文件里是你的浏览器编号.Session的状态是存储在服务器端,客户端只有session id;而Token的状态是存储在客户端。

 3.cookie,sessionStorage,localStorage

cookie

cookie是存在浏览器上的一小段数据。用来记录某系页面关闭或者刷新后仍需要记录的信息。

cookie可以使用js在浏览器直接设置,也可以在服务器端使用HTTP协议规定的set-cookie来设置。

一般cookie的容量为4k左右。

document.cookie查看当前浏览网站的cookie

localStorage和sessionStorage

localStorage 的优势

  •  1、localStorage 拓展了 cookie 的 4K 限制。
  •  2、localStorage 会可以将第一次请求的数据直接存储到本地,这个相当于一个 5M 大小的针对于前端页面的数据库,相比于 cookie 可以节约带宽,但是这个却是只有在高版本的浏览器中才支持的。

localStorage 的局限

  •  1、浏览器的大小不统一,并且在 IE8 以上的 IE 版本才支持 localStorage 这个属性。
  •  2、目前所有的浏览器中都会把localStorage的值类型限定为string类型,这个在对我们日常比较常见的JSON对象类型需要一些转换。
  •  3、localStorage在浏览器的隐私模式下面是不可读取的。
  •  4、localStorage本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡。
  •  5、localStorage不能被爬虫抓取到。

localStorage 与 sessionStorage 的唯一一点区别就是 localStorage 属于永久性存储,而 sessionStorage 属于当会话结束的时候,sessionStorage 中的键值对会被清空。

4.常见问题

①cookie放哪里,cookie能做的事情和存在的价值

Cookie

  • cookie是存在浏览器上的一小段数据。用来记录某系页面关闭或者刷新后仍需要记录的信息。
  • cookie可以使用js在浏览器直接设置,也可以在服务器端使用HTTP协议规定的set-cookie来设置。
  • 一般cookie的容量为4k左右。
  • document.cookie查看当前浏览网站的cookie

Cookie干嘛用的?Cookie存在的价值

  • 1、会话状态管理(如用户登录状态、购物车、游戏分数、其它需要记录的信息)
  • 2、个性化设置(如用户自定义设置、主题等)
  • 3、精准广告。(平常浏览网页时有时会推出商品刚好是你最近浏览过,买过的类似东西,这些是通过cookie记录的。)

cookie的引用为了解决什么问题

由W3C组织提出,最早由Netscape社区发展的一种机制。由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。目前Cookie已经成为标准,所有的主流浏览器如IE、Netscape、Firefox、Opera等都支持Cookie。

Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。

③cookietoken都存放在header里面,为什么只劫持前

https://www.jianshu.com/p/ce9802589143(这篇文章讲的很好)

因为传统的cookie保存的session id,服务器会根据这个session id,确保服务器与客户端对话;这是的cookie是有状态的,意味着验证记录或者会话需要一直在服务端和客户端保持。而token是无状态的,服务器不记录哪些用户登录了或者哪些 JWT 被发布了,只判断token是否有效,通常我们都会给token设置有效时间,来确保不被劫持。所以劫持cookie比劫持token,更有效,毕竟cookie在某种情况下可以一直使用下去,而token不行。

缓存相关的HTTP请求头

Cache-Control:在响应头中设置,用于通知浏览器该资源需要被缓存

 Expires:其作用也是设置缓存时间(什么时候过期),但是在设置了cache-control的情况下会被覆盖

Last-Modified:表示该文件的最后修改日期,是文件属性和服务端没关系

http缓存控制

⑤HTTP的缓存机制

缓存的重要性不言而喻,通过网络请求资源缓慢并且降低了客户端的用户体验,增添了服务端的负担。很多短期之内不会经常发生变化的资源文件没必要每次访问都想服务端进行数据请求,而缓存策略的使用就是为了改善客户端的呈现时间,降低服务端的负担。

对于HTTP的缓存机制来说,策略体现在HTTP的头部信息的字段上,而这些策略根据是否需要重新向服务器端发起请求可以分为强缓存协商缓存两大类。

强缓存相关的HTTP header 的字段

  • Expires(expires 字段规定了缓存的资源的过期时间
  • Cache-Control(缓存方式)

 协商缓存相关的HTTP header 的字段

  • Last-Modified 和 If-Modified-Since(让服务器去判断是否在此时间之后资源内容发生了变化)
  • Etag 和 If-None-Match(判断资源是否改变)

304 : 资源未改变

412:服务器在验证在请求的头字段中给出先决条件时,没能满足其中的一个或多个。这个状态码允许客户端在获取资源时在请求的元信息(请求头字段数据)中设置先决条件,以此避免该请求方法被应用到其希望的内容以外的资源上。

csrf跨站攻击怎么解决

 

⑦xsrf跨域攻击的安全性问题怎么防范

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值