cookie__HTTPS

目录

  • [1. cookie](#1. cookie)
    • [1.1 使用 cookie 所带来的问题隐患](#1.1 使用 cookie 所带来的问题隐患)
    • [1.2 个人私有信息被泄露](#1.2 个人私有信息被泄露)
    • [1.3 cookie 文件被盗取](#1.3 cookie 文件被盗取)
  • [2. HTTPS 概念理解](#2. HTTPS 概念理解)
    • [2.1 加密和解密](#2.1 加密和解密)
    • [2.2 数据摘要 && 数据指纹](#2.2 数据摘要 && 数据指纹)
  • [3. HTTPS 的加密方式](#3. HTTPS 的加密方式)
    • [3.1 只使用对称加密](#3.1 只使用对称加密)
    • [3.2 只使用非对称加密](#3.2 只使用非对称加密)
    • [3.3 双方都使用非对称加密](#3.3 双方都使用非对称加密)
    • [3.4 非对称加密 + 对称加密](#3.4 非对称加密 + 对称加密)
    • [3.5 中间人攻击](#3.5 中间人攻击)

cookie 是一个 HTTP 对登陆用户的会话保持功能,通过使用 cookie,网站可以在用户关闭浏览器后仍然保持用户的登录状态。

当我们首次访问一个网站并进行登录时,网站会通过 HTTP POST 请求将用户名和密码发送给服务器进行身份验证。比如,我们在访问 B 站时,第一次访问需要登录,输入账号和密码后,服务器会接收到我们的登录请求并验证身份。验证成功后,B站会在后端进行认证,查找数据库中是否有匹配的用户信息。如果存在匹配的记录,说明用户合法,服务器会返回一个响应,允许用户登录。

在 HTTP 响应中,除了返回正常的页面内容外(比如重定向到首页,状态码置为302),在 HTTP 响应报头中还会有 一个 Set-Cookie 字段,这个字段会在浏览器中保存用户的登录信息,比如用户名、密码等。B站将这些信息通过 Cookie 传递给浏览器,浏览器会把它保存为一个小文件,通常称为 Cookie 文件。之后,只要浏览器再次访问 B站,浏览器会自动在每次请求中携带这个 Cookie 文件中的内容,B站服务器就能够根据这些信息识别出用户身份,验证是否已登录,因此用户无需再次输入账号和密码。

至于浏览器如何保存 Cookie,它有两种保存方式。第一种是内存级,这意味着浏览器只将 Cookie 保存在内存中,关闭浏览器后,Cookie 信息就会丢失,用户需要重新登录。第二种是文件级,即 Cookie 会被保存到磁盘中的一个文件里,即使关闭浏览器或重启计算机,Cookie 信息依然会存在,用户可以继续使用登录状态访问网站。这两种方式的选择通常取决于浏览器的配置和安全设置。

并且,我们也可以在已登录的网站中找到保存的 cookie,里面存储着cookie的相关字段。当删除该网站的cookie数据后,关闭浏览器,重新打开就会发现需要重新验证登录了。

cpp 复制代码
response_header += "Set-Cookie: name=outlie\r\n"; 
response_header += "Set-Cookie: desc=小帅\r\n"; 

但是,如果当我们不小心访问到 "钓鱼" 网站,那么黑客可能通过这些网站在本机植入木马病毒,然后在后台启动一些不明程序,该程序可能会在我们的浏览器中开放一个端口,然后扫描你电脑中的所有的 cookie 文件并偷走。

我们都知道,当我们把个人信息通过 cookie 保存在浏览器,后续再次访问该网站时,服务端会自动做身份认证,不需要重新登录。那么假设黑客成功盗取我们本地电脑上的 cookie 文件后,并且黑客也同样使用 htpp 协议去访问相同的网站,由于黑客拥有用户的 cookie 文件,那么在身份验证时,黑客就等于用户本身,黑客可以直接登录该网站,接着访问当前用户可以访问的所有资源。

这种情况类似于我们常见的QQ被盗号的情况,QQ在登录时底层也是类似于 http 协议,那么就说明 QQ 也一定有自己的一些cookie 信息。那么当我们QQ的 cookie 文件被盗取后,黑客同样同样可以以用户的身份去访问当前用户的所有信息。

那么,面对上述问题,我们需要回归到问题本身,我们为什么要将用户的登录信息存储在 cookie 中?因为如果不使用cookie,那么用户每次访问都需要身份认证、网站都要求用户重新登录,这对用户来说会造成极大的不便,降低用户体验。因此,我们需要通过使用 cookie 来保持用户的登录状态。但是,使用 cookie 又可能会造成 cookie 被盗取,并且这个问题不是最严重的,cookie 里面保存的可是个人的私密信息(用户名和密码)。因此 cookie 被盗取,黑客不仅仅可以以用户本人的身份去访问用户所能访问的所有资源,同时,用户的私密信息也被泄漏了,这才是最严重的问题。

因此,我们一共需要解决两个问题:

  • 个人的 cookie 文件被盗取的问题
  • 个人私有信息被泄露的问题

1.2 个人私有信息被泄露

首先,我们必须承认,个人的防范能力相对于企业级的安全防护是非常薄弱的,大多数普通用户的电脑在黑客面前就相当于是在裸奔。这也是为什么现在有了像360这类杀毒软件,不过尽管它们能提供一些防护,但依然有滞后性,很多时候用户的个人信息已经泄露,木马病毒才被发现。因此,我们必须承认客户端的防范能力几乎是为0的,那么我们把用户的私密信息放在了防范能力几乎为0的客户端,显然是不合理的。

因此为了解决这个问题,客户端不再依赖 cookie 存储敏感信息,而是通过服务端来管理和存储用户的认证信息。当用户首次访问时,仍然需要输入用户名和密码进行认证。认证通过后,服务器会为该用户生成一个 Session 文件,这个文件记录了用户的登录状态、用户名、密码及其他用户登录相关的信息,但是这些数据不会保存在客户端的 cookie 中。并且,服务器还会为每个 Session 文件生成一个唯一的 Session ID,这个ID是在整个服务器中是唯一的,不会与其他用户的 ID 冲突。并且,这个Session 文件是以 Session ID 命名的。

紧接着,在 HTTP 响应时调用 set-cookie 将 Session ID 写回到浏览器的 Cookie 文件中。之后,用户每次请求时,浏览器都会自动在请求中携带这个 Session ID。服务器接收到客户端的请求后,会根据 Session ID 查找对应的 Session 文件,如果找到了且没有过期,就直接认为该用户已经成功认证;如果没有找到 Session ID,或者 Session ID 过期,服务器就会要求用户重新登录。

  • 那么当前这种方案(session + cookie)与一开始的方案(只用 cookie)有什么本质的区别呢??

    黑客同样通过某些网站像用户本地植入病毒,盗取用户的 cookie 文件,那么黑客也一样拿到了用户的 Session ID,一样可以通过服务器端的身份验证,然后访问用户所能访问到的资源。

    虽然黑客同样可以以用户的身份去访问用户所能访问的所有资源。但是,用户的所有私人信息不再泄漏!因为黑客只能拿得到保存在用户本地的 Session ID,而用户的私人信息保存在服务器的 Session 文件中,并且黑客也不敢轻易的去侵入企业的服务器。

因此,通过这种方式,用户的敏感信息就不再存储在浏览器端,而是集中保存在服务器端,从而减少了信息泄露的风险。

因为 Session ID 是由服务器端统一分配管理的,既然服务端可以给客户端分配,那么它自然就有回收的能力。比如,当服务器端检测到当前用户的访问异常(一分钟前在杭州,下一分钟在广州,可能吗???),那么服务器端就把当前用户的 Session ID 设置为暂停状态,并且要求用户重新认证登录,如果认证失败,删除分配给当前用户的 Session ID。

因此,即便服务端无法完全规避由于客户端的防范能力过低导致的 cookie 文件被盗取,然后被黑客冒充访问等问题,但是依旧可以通过对异常情况的检测,然后对 Session ID 进行暂停、回收等操作来达到控制客户端的目的。

2. HTTPS 概念理解

  • HTTPS 是什么

    HTTP 请求或者响应时,报文内的所有字段信息都是明文,而报文是可以直接被获取的,因此 HTTP 是非常不安全的。而 HTTPS 也是⼀个应⽤层协议,与 HTTP 是共存的,也就是说,用户可以自由的选择通过那种协议进行网络通信。

    网络基础(一) 中我们谈过,网络通信的本质就是贯穿网络协议栈的过程,对于 HTTP 而言,它属于应用层协议, HTTPS 则是在 HTTP 协议的基础上(传输层之上,HTTP协议之下)引⼊了一层软件层(也属于应用层,TLS、SSL),用于对数据进行加密和解密。因此,如果是网络通信的过程中,没有贯穿该软件层,则是 HTTP 协议,贯穿网络协议栈时经过 TLS、SSL,则代表 HTTPS。

2.1 加密和解密

  • 概念

    加密就是把明文(传输的数据) 进行一系列变换,生成密文;而解密就是把 密文 再进行一系列变换,还原成明文。在这个加密和解密的过程中,往往需要一个或者多个中间的数据,来辅助进行这个过程,这样的数据称为密钥。

  • 为什么要加密

    这就是需要谈及臭名昭著的 "运营商劫持" 事件了。相信很多伙伴在刚开始接触计算机时都会遇到过,在浏览器中搜索下载某一个软件,最终下载安装后发现不是自己想要的。

    如上图所示,张三原本计划下载的是 A 软件,但点击下载后,下载链接被 "偷偷地" 缓存了 B 软件。这个过程的本质是这样的,当我们点击下载后,浏览器会在后台发送一次 HTTP 请求,该请求本应该指向到 A 软件的服务器,去获取实际的下载文件。但是在这个过程(浏览器发送请求,到请求递达目的地)所有的网络流量都需要经过一个中间人,即运营商。因此,如果这个请求没有加密,那么运营商就可以获取请求的内容是什么(即它能够知道你要下载的链接是哪个)。而运营商则是坚定落实 "有钱能使鬼推磨" 理念,它 "偷偷地" 把你的下载链接替换成 B 软件,最终导致你的请求被重定向到 B 软件的服务器上。

  • 常见的加密方式

    • 对称加密

      采用单钥密码系统的加密方法,同一个密钥可以同时用作为信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。特征:加密和解密所用的密钥是相同的

      常见对称加密算法(了解):DES、3DES、AES、TDEA、Blowfish、RC2等

      特点:算法公开、计算量小、加密速度快、加密效率高对称加密其实就是通过同一个"密钥",把明文加密成密文,并且也能把密文解密成明文

      示例:int a = 10, keys = 20; 我们将 a 作为明文,keys 作为密钥,发送时我们不会直接发送明文,而是 int data = a ^ keys,那么对方收到的 data 就是密文,那么它需要拿着 keys 对 data 进行异或运算,最终得到一开始的明文。这其中的 keys 就是密钥,而这种使用同一个密钥加密解密的方式,我们称为对称加密。

    • 非对称加密

      需要两个密钥来进行加密和解密,这两个密钥是公开密钥(public key,简称公钥) 和私有密钥(private key,简称私钥)。

      常见非对称加密算法(了解):RSA,DSA,ECDSA

      特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。

      非对称加密要用到两个密钥,一个"公钥",一个"私钥"。公钥和私钥是配对的,最大的缺点就是运算速度非常慢,比对称加密要慢很多。通过公钥对明文加密,变成密文,通过私钥对密文解密,变成明文;也可以反着用(但通常都是公开加密)。换言之,如果一个明文通过公钥加密,那么无法通过公钥解密,只有私钥能够解密,反之同理。而私钥一般只有本主机拥有,这就意味着能够解密的人非常非常少。

2.2 数据摘要 && 数据指纹

  • 数字指纹(数据摘要),其基本原理是利用单向散列函数(Hash函数) 对信息进行运算,生成一串固定长度的数字摘要(比如一篇10w字文章,经过hash摘要算法,最终生成一段固定长度的字符串)。数字指纹(数据摘要) 并不是一种加密机制(因为 hash 是不可逆的,并无法通过相同的 hash 算法将 value 还原为 key,即无法解密,而没有解密,自然也就算不上加密),但它可以用于判断数据有没有被窜改。

  • 摘要常见算法:有MD5、SHA1、SHA256、SHA512等,算法把无限的映射成有限,因此可能会有碰撞(两个不同的信息,算出的摘要相同,但是概率非常非常低)

  • 摘要特征:和加密算法的区别是,摘要严格意义不是加密,因为没有解密,只不过从摘要很难反推原信息,通常用来进行数据对比

  • 当同一份数据发生改动(哪怕的一个比特位的内容发生改变),生成出来的数据摘要也会存在非常大的差别。而当数据原封不动,没有任何修改,那么通过同样的散列算法,生成的数据摘要就一定是完成一致的。

    因此,在网络传输数据的同时带上数据摘要,接收方即可以通过相同的散列函数,再次生成数据摘要,对比发送方的数据摘要,以此来判断数据有没有被篡改。

  • 网盘案例

    网盘的用户是非常庞大的,因此不同用户之间的数据是可能发生重叠的,那么作为网盘的工程师,你不会傻傻的浪费一份空间,去存储完成相同的数据。因此网盘会对用户上传的所有数据做 hash 散列,形成数据摘要。

    假设张三上传了一部 A 电影,后来李四也上传了 A 电影,那么在李四上传之前,网盘的客户端会在用户的本地,使用同样的 hash 散列算法,形成数据摘要,然后将摘要上传到网盘,在网盘的后台做搜索,查找是否有相同的数据摘要。如果找到了,那么不会将李四上传的电影再存储一遍,而是把网盘中已经存在的这一份数据,关联一份给李四。

3. HTTPS 的加密方式

3.1 只使用对称加密

  • 如果通信双方时都各自持有同一个密钥X,且没有别人知道,双方的通信安全是可以得到保障的。引入对称加密之后,即使数据被截获,由于黑客不知道密钥是啥,因此就无法进行解密。

  • 请求是客户端发起的,数据也是来自客户端,密钥自然也是客户端生成的,那么问题是,服务器端该如何得知密钥 X ?

    因此,密钥也需要通过网络传输,由客户端发送给服务器。既然是网络通信,那是不是一样有可能像明文传输一样,被中间人截获,然后用于解密后续传输的密文。

    那就继续对密钥进行加密呗!

    那密钥加密所使用的密钥又如何传输??这就使问题陷入了一个死循环。

    因此这个方案是不具备可行性的,首次进行通信时,无法同步双方的秘钥。

3.2 只使用非对称加密

  • 鉴于非对称加密的机制,如果服务器先把公钥以明文方式传输给浏览器,之后浏览器向服务器传数据前都先用这个公钥加密好再传,从客户端到服务器信道似乎是安全的(有安全问题,后面讲),因为只有服务器有对应的私钥,因此只有服务器能解开公钥加密的数据。

    但是当服务器响应给客户端的密文,由于中间人的存在,他一样能够被截获并破解。因此方案二,只是保证了单向数据的安全(有安全问题),并且运算速度比较慢。

3.3 双方都使用非对称加密

  • 服务端拥有公钥 P_svr、私钥 S_svr,客户端拥有公钥 P_cli、私钥 S_cli

    客户和服务端交换公钥

    客户端给服务端发信息:先用 P_svr 对数据加密,然后发送,而对应的私钥只有服务器拥有,因此只有服务器能解密

    服务端给客户端发信息:先用 P_cli 对数据加密,然后发送,而对应的私钥只有客户端拥有,因此只有客户端能解密

  • 同样的,这种方案虽然解决了方案二的单向数据问题,但一样有安全问题,而且通信速度非常慢。

3.4 非对称加密 + 对称加密

  • 先解决效率问题

    服务端生成非对称公钥P 和 私钥S,客户端发起 https 请求,获取服务端公钥P

    客户端在本地生成对称密钥X,再通过公钥 P 对明文加密,然后发送给服务器。由于中间的网络设备没有私钥,所以即使截获了数据,也无法破解,也就无法获取到对称密钥。

    服务器通过私钥 S 解密,还原出客户端发送的对称密钥X,并且使用这个对称密钥加密给客户端返回的响应数据。后续客户端和服务器的通信都只需要使用对称加密即可,并且由于该密钥只有客户端和服务器两个主机知道,其他主机/设备 不知道密钥,因此截获数据也就变的没有意义。

    这种方案只需要在传输对称密钥时,使用非对称密钥进行加密传输,后续的数据传输都使用的是对称加密,因此通信效率得到提高。

3.5 中间人攻击

  • 确实,在方案2/3/4中,客户端获取到公钥 P 之后,生成密钥 X,并用服务端的公钥 P 对密钥 X 进行加密,所以即便中间人截获到了数据,也无法破解出客户端生成的密钥 X,因为只有服务器拥有私钥 S 能够解密。
  • 但是上面可是理想状态,中间人的攻击往往在最开始握手协商时就进行了!

    服务器生成非对称加密的公钥 P_svr,私钥 S_svr

    中间人同样生成非对称加密的公钥 P_mid,私钥 S_mid。

    客户端向服务器发起请求,服务器明文传送公钥 P_svr 给客户端

    中间人截获数据报文,提取公钥 P_svr 并保存好,然后将劫持报文中的公钥 P_svr 替换成为自己的公钥 P_mid,并伪造报文发给客户端

    客户端收到报文,提取公钥 P_mid (客户端无法得知公钥被更换过了),客户端生成对称秘钥X,用公钥 P_mid 加密 X,形成报文发送给服务器

    中间人劫持客户端发送的报文,直接用自己的私钥 S_mid 进行解密,得到通信秘钥 X,再用曾经保存的服务端公钥P_svr 加密后,将报文推送给服务器

    服务器拿到报文,用自己的私钥 S_svr 解密,得到通信秘钥 X

    双方开始采用 X 进行对称加密通信。但是中间人同样拥有,因此它可以劫持数据,进行窃听甚至篡改

  • 上面的攻击方案,同样适用于方案2,方案3问题,本质问题都是因为客户端无法甄别自己收到的公钥是否是合法的,是否真的来自服务器端,那么我们想要解决中加入篡改公钥的问题,我们就需要解决如何让客户端得知,自己收到的公钥是否合法,如果合法,则继续通信,否则 "有内鬼,交易终止!"。

相关推荐
爱吃喵的鲤鱼2 小时前
Linux——网络(https)
linux·网络·https
祈澈菇凉2 小时前
详细解释一下HTTPS握手过程中的密钥交换?
网络协议·http·https
Strive_Sun2 小时前
Windows 下搭建 googletest 测试框架(C/C++)
c语言·开发语言·c++·windows
庸了个白2 小时前
错误报告:WebSocket 设备连接断开处理问题
网络·websocket·网络协议
小禾苗_2 小时前
C++ ——基础进阶
开发语言·c++
别开生面的阿杰2 小时前
C++--iomanip库
开发语言·c++
羽觞醉月112 小时前
C++基础 | 线程`std::thread`
开发语言·c++·算法
不想编程小谭3 小时前
从小白开始的动态规划
c++·算法·动态规划
YGGP3 小时前
【GeeRPC】Day5:支持 HTTP 协议
http·rpc·golang
FIN技术铺3 小时前
HTTP请求&响应分析:HTTP/1.1→HTTP/2
网络·网络协议·http