浏览器05

具体参考这篇文章

由于http是无状态协议,一旦客户端和服务器的数据交换完毕,就会断开连接,再次请求会重新连接,这说明服务端单从网络连接上是没有饭吧直到用户身份的。那就给每次新的用户请求时,给它颁发一个身份证(独一无二),下次访问时,必须带上身份证,这样服务器就会知道是谁来访问了,针对不同用户,做出不同响应,这就是cookie的原理。其实cookie是纯文本,没有可执行代码。储存一些服务器需要的信息,每次请求站点,会发送相应的cookie,这些cookie可以用来辨别用户身份信息

用户首次访问服务器,服务器会返回一个独一无二的识别码(id=12345),这样服务器可以用这个吗来跟踪用户的信息(购物车历史、地址信息)。cookie可以包含任意的信息,不仅仅是id,客户端会记录服务端返回来的set cookie首部中的cookie内容,并将cookie存储在浏览器的cookie数据库中,当用户访问同一站点时,浏览器会挑选当时该站点颁发的id=xxxxx身份证,并在cookie请求首部发送过去。

cookie分为会话cookie(临时cookie)和持久cookie(存在硬盘里)

发展史

1、很久以前,web基本上激素hi文本的浏览而已,既然是浏览,作为服务器,不需要记录谁在某一段时间里都浏览了什么文档,每次请求都是一个新的HTTP协议,就是请求响应,尤其不用记住是谁刚刚发了http请求,每个请求对我来说都是全新的。
2、但是随着交互式web应用的兴起,像在线购物网站,需要登录的网站等等,马上就面临一个问题,那就是要管理会话,必须记住那些人登录系统,哪些人往自己的购物车放商品,也就是说要把每一个人区分开,但是http是一个无状态的协议,所以想出的办法就是给每一个用户颁发一个会话标识(seddion id),这其实就是一个随机的字符串,每个人收到的都不一样,每次的用户发送一个请求的时候,就把这个字符串一起发送过来,这样服务器就能区分每一个用户了。
3、这样的话用户是识别了,可是服务器的负担就重了,因为客户端只需要保存自己的session id,但是服务器要保存所有人的session id,如果访问服务器的用户多了,那么服务器就崩溃了。

这对服务器是一个巨大的开销,严重的限制了服务器扩展能力,比如说我用两个及其组成了一个集群,小F通过机器A登录了系统那session id就会保存在机器A上,假如小F下一次请求被转发到机器B怎么办?机器B没有下F的session id

有时候会采用一点小伎俩:session sticky,就是让小F的请求一直粘连在机器A上,但是这也不管用,要是机器A挂掉了,还得转到机器B去。

那只好做session的复制,把sessionid在两个机器之间搬来搬去,会很麻烦。

后来有个方法:把session id集中存储到一个地方,所有的机器都来访问这个地方的数据,这样一来,就不用复制了,但是增加了单点失败的可能性,要是哪个负责session的机器挂掉了,所有人都得重新登录以便,估计太麻烦了。
4、于是有人就在思考,为什么要服务器保存这个session id呢,直接让每个客户端去保存就好了。
可是如果不保存这些session id,怎么验证客户端发给服务器的session id的确是服务器生成的呢?如果不去验证,服务器都不知道它们是不是合法的用户,哪些不怀好意的人就可以任意伪造session id了。

所以关键点就是验证
比如小f已经登陆了系统,服务器给它发送一个令牌(token),里面包含了小f的user id,下一次小f再次通过http请求访问服务器的时候,把这个token通过http header带过来不就可以了。

不过这和sessionid没有本质区别,任何人都可以伪造,所以得想点办法不让别人伪造

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

这个token服务器不保存,当小f把这个token
发送给服务器的时候,服务器再用同样的算法和同样的密钥,对数据再计算一次签名,和token中的签名做一个比较,结果相同就知道小f已经登录过了,并且可以直接得到小f的user id,如果不相同数据部分肯定被人纂改过,服务器就可以告诉客户端对不起没有认证!

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

当然如果一个人的token被人偷走了,那服务器也没有你办法,服务器就会认为小偷是合法用户,服务器用它的CPU计算时间获取它的session存储空间。

cookie是一个非常具体的东西,指的就是浏览器里面能永久存储的一种数据,仅仅是浏览器实现的一种数据存储功能。
cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的文本文件内,下次请求统一网站时会把该cookie发送给服务器。由于cookie时存储在客户端上的,所以浏览器加入了一些限制确保cookie
不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。

session

session从字面上讲,就是会话。这个就类似于我们和一个人交谈,我们怎么知道他时张三而不是李四呢?对方肯定有某种特征(长相等)表明他就是张三。

session就是类似的道理,服务器要知道当前发请求给自己的是谁。为了做这种区分,服务器就要给每个客户端分配不同的身份标识,然后客户端每次像服务端发送请求的时候,都带上这个身份标识,服务器就知道这个请求来自于谁了。至于客户端怎么保存这个身份标识,可以有很多种方式,对于浏览器客户端大家都默认采用cookie的方式。

服务器使用session把用户的信息临时保存在了服务器上,用户离开网站后session会被销毁。这种用户信息存储方式相对cookie来说更安全,可是session有一个缺陷:如果服务器做了负载均衡那么下一个操作请求到了另一个服务器的时候session会丢失。

token

在web领域基于token的身份验证随处可见。在大多数使用webAPI的互联网公司中,tokens是多用户下处理认证的最佳方式。
以下几点特性会让我们在程序中基于token的身份验证:

  • 无状态、可扩展
  • 支持移动设备
  • 跨程序调用
  • 安全

哪些基于token的身份验证的大佬们,大部分见到过的API和web用于都使用tokens。例如facebook、twitter、github等。

token的起源

在介绍基于token的身份验证的原理与优势之前,不妨先看看之前的认证都是怎么做的。

基于服务器的验证

我们都知道http是无状态的,这就意味这程序需要验证每一次请求,从而辨别客户端的身份。在这之前,程序都是在服务器存储的登录信息来辨别请求的,这种方式一般都是通过存储sessio来实现的。
随着web应用程序,以及移动端的兴起,这种验证的方式逐渐暴露出了问题。尤其是在可扩展性方面。

暴露的问题:

  • session:每次认证用户发起请求时,服务器需要去创建一个记录来存储信息。当越来越多的用户发请求时,内存的开销也会不断增加。
  • 可扩展性:在服务端的内存中使用session存储登录信息,伴随而来的时可扩展性问题。
  • CORS(跨域资源共享):当我们需要让数据跨多台移动设备上使用时,跨域资源共享是一个让人头疼的问题,在使用Ajax抓取另一个域的资源就会出现禁止请求的情况。
  • CSRF(跨站请求伪造):用户在访问银行网站时,它他们容易受到跨站请求伪造的攻击,并且能够利用器访问其他的网站。
    在这些问题中,可扩展性是最突出的。因此我们有必要去寻求一种更为有效的办法。

基于token的验证原理

基于token的身份验证是无状态的,我们不用将用户信息在服务器或session中。
这种概念解决了在服务端存储信息时的许多问题。no session意味着我们的程序需要去增减服务器,而不用担心用户是否登录。

基于token的身份验证如下:

  • 用户通过用户名和密码发送请求
  • 程序验证
  • 程序返回一个签名的token给客户端
  • 客户端存储token,并且用于没vi发送请求
  • 服务端验证token并返回数据

每一次请求都需要token。token‘应该在http的头部发送从而保证了http请求无状态。我们同样通过设置服务器属性access-control-allow-origin: * ,让服务器能接收到来自于所有的请求。需要注意是,在ACAO头部表明* 时。不得带有像http认证,客户端SSL整数和cookie的整数。

  • 用户登录校验校验成功后就返回token给客户端
  • 客户端收到数据后保存到客户端
  • 客户端每次访问API时携带token到服务器端
  • 服务器端采用filter过滤器校验。校验成功后则返回请求数据,校验失败则返回错误码

当我们在程序中认证了信息并取得token之后,我们便能通过这个token做许多事情。我们甚至能基于创建一个基于权限的token传给第三方应用程序,这些第三方程序能够获取到我们的数据(当然只有在我们允许的特定的token)

token的优势

无状态、可扩展
在客户端存储的token时无状态的,并且能够被扩展。基于这种无状态和不存储session信息,负载均衡器能够将用户信息从一个服务器传到另一个服务器上。

如果我们将已校验的用户的信息保存到session中,则每次请求都需要用户向已验证的服务器发送验证信息。用户量增大时,可能会造成一些拥堵
但是,使用token后这些问题都迎刃而解,因为token自己hold住了用户的验证信息。

安全性

请求中发送token而不再是发送cookie能够放置CSRF(跨站请求伪造)。即使在客户端使用cookie存储token,cookie也仅仅是一个存储机制而不是用于认证。不讲信息存储在session中让我们少了对session的操作。

token是有时效的,一段时间之后,用户需要重新验证。我们也不一定需要等到token自动失效,token有撤回的操作,通过token revocation可以使一个特定的token或是一组有相同认证的token无效

可扩展性

token能够创建与其他程序共享权限的程序。例如,能够将一个随便的社交账号和自己的大号联系起来。当通过服务登录时,我们可以将这些buffer附到数据流上,使用token时,可以提供可选的权限给第三方应用程序。当用户想让另一个应用程序访问他们的数据时,我们可以通过建立自己的API,得出特殊权限的token。

多平台跨越

我们提前先来讨论一下CORS(跨域资源共享),对应用程序和服务进行扩展的时候,需要介入各种各样的设备和应用程序。

基于标准

创建token时,可以设定一些选项。

三者比较

从安全性优先级来说:

优先级

1
Cookie<session<token

安全性

  • cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session
  • HTTP是一种无状态协议,服务器没有办法单单从网络连接上面知道访问者的身份,为了解决这个问题,就诞生了CookieCookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。

session:

  • session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie
  • 关闭浏览器不会关闭session,它具失效日期,失效后服务器认为客户端停止了活动,并删除session以节省空间

Token:

  • 作为身份认证 token安全性比session好,因为每个请求都有签名还能防止监听以及重放攻击
  • Oauth token提供的是认证和授权,认证针对用户,授权针对app
  • token的生成一般是采用uuid保证唯一性,当用户登录时为其生成唯一的token,存储一般保存在数据库中。token过期时间采用把token二次保存在cookie或session里面,根据cookie和session的过期时间去维护token的过期时间

开发过程举例:

案例一:
项目中我们的用户数据可能需要和第三方共享,或允许第三方调用我们的API则用token

案例二:
公司内部的网站,自己的App,就可以用cookie、session
一般来说我们可以将登录信息放在session,其他信息保存在cookie

案例三:
观察微信、支付宝登录接口用的就是token

总结

客户端连接服务器,服务器生成session id(会话ID),返回客户端。浏览器客户端一般默认采用cookie方式保存这个session id(身份标识)。为防止客户端伪造session id,验证是关键,即算法+密钥对数据做一个签名。客户端将数据+签名一起作为token发送到服务器,服务端通用用算法+同样的密钥对数据计算签名,与客户端带过来的签名对比,相同则表明客户端已登录,不同则可能数据被篡改,返回验证失败。

-------------本文结束感谢您的阅读-------------