一.Cookie 和 Session
1.为什么要有Cookie
(1)HTTP实际上是一种无状态协议,HTTP的每次请求/响应之间是没有任何关系的,但你在使用浏览器的时候发现并不是这样的 ; 比如当你登录一次爱奇艺后,就算你把爱奇艺网站关了甚至是重启电脑,当你再次打开爱奇艺网站时,CSDN并没有要求你再次输入账号和密码,这实际上是通过cookie技术实现的,点击浏览器当中锁的标志就可以看到对应网站的各种cookie数据。
????????
(2)HTTP是一种无状态协议,不会记录用户的登陆状态。当你在B站刷视频时,每点击一个页面都要一次登陆身份认证,这样来说对于用户太麻烦。有一种独立技术来帮我们支持,这种技术目前现在已经内置到HTTP协议当中了,叫做cookie。
????????????????
2.Cookie的原理
- 第一次登录某个网站时,需要输入我们的账号和密码进行身份认证(输入的账号,密码是发送到服务器上面进行认证的,并不会保存在本地),此时如果服务器经过数据比对后判定你是一个合法的用户,那么为了让你后续在进行某些网页请求时不用重新输入账号和密码,此时服务器就会进行Set-Cookie的设置。(Set-Cookie也是HTTP报头当中的一种属性信息)
- 当认证通过并在服务端进行Set-Cookie设置后,服务器在对浏览器进行HTTP响应时就会将这个Set-Cookie响应给浏览器。而浏览器收到响应后会自动提取出Set-Cookie的值,将其保存在浏览器的cookie文件当中,此时就相当于我的账号和密码信息保存在本地浏览器的cookie文件当中
- 从第一次登录认证之后,浏览器再向该网站发起的HTTP请求当中就会自动包含一个cookie字段,其中携带的就是我第一次的认证信息,此后对端服务器需要对你进行认证时就会直接提取出HTTP请求当中的cookie字段,而不会重新让你输入账号和密码了; 即在第一次认证登录后,后续所有的认证都变成了自动认证.
- 我们的浏览器第一次首次登录时不携带cookie,当认证成功之后服务器会在自己的response里包含set—cookie这个字段,写入到浏览器当中。浏览器保存这个cookie以文件的形式保存,从此以后只要我们登陆成功过,再发起http请求时会自动带上cookie在request里面,服务器收到request请求会提取cookie信息,对其进行自动认证,从此以后再也不用登陆了。
????????
3. Cookie的存储
Cookie本质是一个文件
cookie文件可以分为两种,一种是内存级别的cookie文件,另一种是文件级别的cookie文件:
- 将浏览器关掉后再打开,访问之前登录过的网站,如果需要你重新输入账号和密码,说明你之前登录时浏览器当中保存的cookie信息是内存级别的。
- 将浏览器关掉甚至将电脑重启再打开,访问之前登录过的网站,如果不需要你重新输入账户和密码,说明你之前登录时浏览器当中保存的cookie信息是文件级别的。
????????????????
4.Cookie安全问题
- 如果你浏览器当中保存的cookie信息被非法用户盗取了,那么此时这个非法用户就可以用你的cookie信息,以你的身份去访问你曾经访问过的网站,我们将这种现象称为cookie被盗取了。
- 比如你不小心点了某个链接,这个链接可能就是一个下载程序,当你点击之后它就会通过某种方式把程序下载到你本地,并且自动执行该程序,该程序会扫描你的浏览器当中的cookie目录,把所有的cookie信息通过网络的方式传送给恶意方,当恶意方拿到你的cookie信息后就可以拷贝到它的浏览器对应的cookie目录当中,然后以你的身份访问你曾经访问过的网站。
?
5.Session ID
- 单纯的使用cookie是非常不安全的,因为此时cookie文件当中就保存的是你的私密信息,一旦cookie文件泄漏你的隐私信息也就泄漏。
- 当前主流的服务器还引入了SessionID这样的概念,,当我们第一次登录某个网站输入账号和密码后,服务器认证成功后还会服务端生成一个对应的SessionID,这个SessionID与用户信息是不相关的。系统会将所有登录用户的SessionID值统一维护起来。
- Session ID就是一个身份标识,服务器端把这个sid以及当前用户的登陆情况统一写在服务器的session文件中。从此以后给客户端返回的时候不返回set-cookie,而是直接返回set-cookie: sid =xxx,只把sid返回 。
- 此时当认证通过后服务端在对浏览器进行HTTP响应时,就会将这个生成的SessionID值响应给浏览器。浏览器收到响应后会自动提取出SessionID的值,将其保存在浏览器的cookie文件当中。后续访问该服务器时,对应的HTTP请求当中就会自动携带上这个SessionID。
- 服务器识别到HTTP请求当中包含了SessionID,就会提取出这个SessionID,然后再到对应的集合当中进行对比,对比成功就说明这个用户是曾经登录过的,此时也就自动就认证成功了,然后就会正常处理你发来的请求.
????????????????
6.小结
- 引入SessionID之后,浏览器当中的cookie文件保存的是SessionID,此时这个cookie文件同样可能被盗取。此时用户的账号和密码虽然不会泄漏了,但用户对应的SessionID是会泄漏的,非法用户仍然可以盗取我的SessionID去访问我曾经访问过的服务器,相当于还是存在刚才的问题。
- 之前的工作方式就相当于把账号和密码信息在浏览器当中再保存一份,每次请求时都自动将账号和密码的信息携带上,但是账号和密码一直在网当中发送太不安全; 现在的工作方式是,服务器只有在第一次认证的时候需要在网络中传输账号和密码,此后在网络上发送的都是SessionID。
- 这种方法虽然没有真正解决安全问题,但这种方法是相对安全的。互联网上是不存在绝对安全这样的概念的,任何安全都是相对的,就算你将发送到网络当中的信息进行加密,也有可能被别人破解。
????????????????
引入SessionID后的好处
- 在引入SessionID之前,用户登录的账号信息都是保存在浏览器内部的,此时的账号信息是由客户端去维护的。
- 而引入SessionID后,用户登录的账号信息是有服务器去维护的,在浏览器内部保存的只是SessionID。
- 虽然SessionID可能被非法用户盗取,但服务器也可以使用各种各样的策略来保证用户账号的安全。
- 服务器的安全性比笔记本高。笔记本的保镖是360,服务器的保镖是一群集群,一大批防火墙,以及一群有经验的工程师
- IP是有归类的,可以通过IP地址来判断登录用户所在的地址范围。如果一个账号在短时间内登录地址发送了巨大变化,此时服务器就会立马识别到这个账号发生异常了,进而在服务器当中清除对应的SessionID的值。这时当你或那个非法用户想要访问服务器时,就都需要重新输入账号和密码进行身份认证,而只有你是知道自己的密码的,当你重新认证登录后服务器就可以将另一方识别为非法用户,进而对该非法用户进行对应的黑名单/白名单认证。
- 当操作者想要进行某些高权限的操作时,会要求操作者再次输入账号和密码信息,再次确认身份。就算你的账号被非法用户盗取了,但非法用户在改你密码时需要输入旧密码,这是非法用户在短时间内无法做到的,因为它并不知道你的密码。这也就是为什么账号被盗后还可以找回来的原因,因为非法用户无法在短时间内修改你的账号密码,此时你就可以通过追回的方式让当前的SessionID失效,让使用该账号的用户进行重新登录认证。
- SessionID也有过期策略,比如SessionID是一个小时内是有效的。所以即便你的SessionID被非法用户盗取了,也仅仅是在一个小时内有效,而且在功能上受约束,所以不会造成太大的影响。
- 任何事情都有两面性,如果不是这些非法用户的存在,现在的服务器肯定是漏洞百出,只有双方不断进行对抗双方才能不断进步
?????????????????
7.实验验证Set-Cookie
(1)代码
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
using namespace std;
int main()
{
//创建套接字
int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
if (listen_sock < 0){
cerr << "socket error!" << endl;
return 1;
}
//绑定
struct sockaddr_in local;
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET;
local.sin_port = htons(8081);
local.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0){
cerr << "bind error!" << endl;
return 2;
}
//监听
if (listen(listen_sock, 5) < 0){
cerr << "listen error!" << endl;
return 3;
}
//启动服务器
struct sockaddr peer;
memset(&peer, 0, sizeof(peer));
socklen_t len = sizeof(peer);
for (;;){
int sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
if (sock < 0){
cerr << "accept error!" << endl;
continue;
}
if (fork() == 0){ //爸爸进程
close(listen_sock);
if (fork() > 0){ //爸爸进程
exit(0);
}
//孙子进程
char buffer[1024];
recv(sock, buffer, sizeof(buffer), 0); //读取HTTP请求
cout << "--------------------------http request begin--------------------------" << endl;
cout << buffer << endl;
cout << "---------------------------http request end---------------------------" << endl;
#define PAGE "index.html" //网站首页
//读取index.html文件
ifstream in(PAGE);
if (in.is_open()){
in.seekg(0, in.end);
int len = in.tellg();
in.seekg(0, in.beg);
char* file = new char[len];
in.read(file, len);
in.close();
//构建HTTP响应
string status_line = "http/1.1 200 OK\n"; //状态行
string response_header = "Content-Length: " + to_string(len) + "\n"; //响应报头
response_header += "Set-Cookie: XiaoMi_MIUI\n"; //添加Set-Cookie字段
string blank = "\n"; //空行
string response_text = file; //响应正文
string response = status_line + response_header + blank + response_text; //响应报文
//响应HTTP请求
send(sock, response.c_str(), response.size(), 0);
delete[] file;
}
close(sock);
exit(0);
}
//爷爷进程
close(sock);
waitpid(-1, nullptr, 0); //等待爸爸进程
}
return 0;
}
????????????????
(2)运行服务器后,用浏览器访问我们的服务器,此时通过Fiddler可以看到我们的服务器发给浏览器的HTTP响应报头当中包含了这个Set-Cookie字段
?????????????????
(3)我们也可以在浏览器当中看到这个cookie,这个cookie的值就是我们设置的XiaoMI_MIUI,此时浏览器当中就写入了这样的一个cookie。
?????????????????
(4)然后我们输入用户名和密码并提交,此时相当于第二次访问我们的服务器,此时通过Fiddler可以看到,由于我们提交表单参数用的是POST方法,因此这里的参数是通过正文的形式提交的,更重要的是第二次的HTTP请求当中会携带上这个cookie信息。?
?
?
??????????????????????
??????????????????????????
????????
二.HTTPS了解?
?1.HTTPS的出现
- 早期很多公司刚起步的时候,使用的应用层协议都是HTTP,而HTTP无论是用GET方法还是POST方法传参,都是没有经过任何加密的,因此早期很多的信息都是可以通过抓包工具抓到的。
- 为了解决这个问题,于是出现了HTTPS协议,HTTPS实际就是在应用层和传输层协议之间加了一层加密层(SSL&TLS),这层加密层本身也是属于应用层的,它会对用户的个人信息进行各种程度的加密。HTTPS在交付数据时先把数据交给加密层,由加密层对数据加密后再交给传输层。
- 通信双方使用的应用层协议必须是一样的,因此对端的应用层也必须使用HTTPS,当对端的传输层收到数据后,会先将数据交给加密层,由加密层对数据进行解密后再将数据交给应用层。
- HTTP把用户的原生数据交付给下层,裸奔;HTTPS对数据进行加密,传输加密过后的数据。
- SSL:非标准的 ,TLS:标准版。这两个本质是一个东西 : SSL更早,标准化后更名TLS
????????????????
2.对称加密和非对称加密
(1)加密的方式可以分为对称加密和非对称加密:
- 采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密(异或)。
- 采用公钥和私钥来进行加密和解密,用其中一个密钥进行加密就必须用另一个密钥进行解密,这种加密方法称为非对称加密。
(2)非对称加密,加密算法复杂,效率比较低。对称加密比较快。
(3)数据如何加密
- 对称加密的效率更高,因此双方在进行正常通信时使用的是对称加密。但双方要进行对称加密通信,此时就要去加密方要把密钥给解密方,此时解密方才能对数据进行解密,但加密方把密钥(密钥也是数据)给解密方时也是需要对密钥进行加密的,解密废没法解密就没法拿到密钥,这就变成了鸡生蛋蛋生鸡的问题了。
- 这里也不可能让加密方给密钥的时候不进行加密,因为那样全世界都知道这个密钥了,后续加密方的加密也就没有意义了。因此刚开始在进行密钥协商的时候需要用非对称加密,在进行数据传输时采用对称加密。
- HTTPS秘钥协商过程是SSL/TLS做的,https触发,SSL/TLS支持。
数据加密过程如下:
- 通信双方建立连接的时候,双方就可以把支持的加密算法作协商,协商之后在服务器端形成非对称加密时使用的公钥和私钥,在客户端形成对称加密时使用的密钥。
- 然后服务器将公钥交给客户端(这个公钥全世界都可以看到),然后客户端用这个公钥对客户端形成的密钥进行加密,将加密后的密钥发送给服务器,服务器拿到后再用它的私钥进行解密,最终服务器就拿到了客户端的密钥。
- 这时客户端和服务器都有了这个密钥,并且其他人是不知道的,此时客户端和服务器就可以进行对称加密通信了。
- 需要注意的是,这里客户端用公钥加密后的密钥只有服务器能够解密,因为在非对称加密当中,数据用公钥加密就必须用私钥解密,而只有服务器才有私钥.
3. 远端服务器的身份认证和中间信息被篡改问题
- 为了让你感知不到,中间服务器也想当一个客户端,代你去访问这个server,Server的公钥再把数据加密,把数据给server,server把数据返回给中间服务器
- ?客户端和服务器的通信细节,中间服务器都能看到。
- ?公钥本身也是一段数据,如果电脑中了木马,病毒,公钥数据就会被获取。般小白的电脑在黑客眼中想大海一样宽阔。????????
?????????????????
(1)相关概念?
- 密钥: 对称加密设置的密码
- 公钥: 公钥用于加密信息和解密数字签名
- 私钥: 私钥用于解密信息和加密消息摘要
- 消息摘要 / 数字指纹 : 对消息(数据)使用HASH算法获取的固定长度的字符串
- 数字签名: 使用私钥加密的消息摘要
- 数字证书:CA用自己的私钥,对需要认证的公钥及相关的信息进行加密
①数字证书颁发过程:?
- 1.用户A首先获得 CA的根证书,即CA的公钥信息
- 2.用户A提交自己的公钥,身份信息等消息
- 3.CA对用户A提交的公钥进行哈希计算得到散列值,然后用CA自己的私钥对得到的散列值进行签名
- 4.CA将用户的公钥,签名和用户信息放入证书中下发给用户A?
②消息摘要(Message Digest)又称作数字摘要(Digital Digest)。它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生。如果消息在途中改变了,则接收者通过对收到消息的新产生的摘要与原摘要比较,就可知道消息是否被改变了, 因此消息摘要保证了消息的完整性 . 消息摘要采用单向Hash 函数将需加密的明文"摘要"成一串128bit的密文,这一串密文亦称为数字指纹(Finger Print)
?????????????????
(2)远端服务器的认证问题
?????????????????
(3)中间信息被篡改问题
- 即使黑客把文本内容修改了,也无法修改数据摘要 ;最后通过数据摘要的对比证明信息是否被篡改.
- 公钥加密,私钥解密--数据通信
- 私钥加密,公钥认证--认证
????????????????
4.常见面试问题
- 面试HTTP和HTTPS区别?? ? ?简单点说就是HTTPS是经过加密的,SSL/TSL。
- 怎么加密?? ? 先是对称加密,然后非对称加密。出于安全的考量现有非对称加密,出于效率考量换成对称加密。
- 如何防止数据被篡改?? ? ? 数据摘要技术,数据签名技术,数据指纹技术来认证怎么认证服务器呢?证书
????????????????????????
????????????????
三.长短连接问题
?????????????????
1.问题: 一个response只有一个body,只能带回来一份资源,一个网页有成百上千个元素,我们今天要把所有元素获得怎么办呢?假设网页中有99张图片,有1个Html怎么获取? 先获取html, html里面有很多标签证明它用了99张图片,依次把99张图片都拿过来才是一个完整的网页。
- 短连接的话:response只能带回一份资源,需要99次重复地先建立链接,传送资源,释放连接。这样的话建立链接的成本就变得非常高。
- 所谓的长连接∶在实际的三次握手之后,当前的网页没有构成一个完整的网页之前,只用同一个链接。一条链接中可以发起多次http请求和响应等我把所有的资源传送完毕之后构成了一张完整网页,短期之内没有新的 http请求了,再把链接断开。?
2.为什么刚开始用短连接,不用长连接呢?
- 在早起的时候网页特别的简单,所有的网页只有文字,没有图片。到后面数据资源越来越多,传输的东西变多了。
- 刚开始用短连接是因为简单,当时网络资源并不大,扛得住。后来网络的情况越来越复杂,网页资源丰富,短连接扛不住,服务器也扛不住了。
3.这样做(长连接)的好处是什么? 提高效率
???????????????? 4.链接的打开和关闭是受谁控制的?? 应用层 TCP提供了建立和关闭链接的功能,致于要不要建立,和释放是由应用层决定的,HTTP有能力控制链接的打开与关闭
5.基于长连接我们可以只基于一条信道,建立一次释放一次就可以实现传送多种网络资源构成─张完整网页。这样能明显减少建立和释放连接的成本,大大提高效率。
6.怎么证明我们需要长连接?? ? 请求和响应的报头中有一个字段Connection : keep alive
7.链接建立和释放是有成本的,OS层面客户端和服务器要创建对应的数据结构。
`?? ? ? ? ? ? ? ? ? ? ???
8.短连接一个请求一个响应,长连接可能有多个请求多个响应,多个请求同时发送在网络里面跑,但是接受的时候还是一个一个的接收。不管发送多少请求,我们读到的第一个永远是请求行,第二步一直按行读取,读到空行证明把第一个请求的请求报头读完了,然后读正文(Content - length有长度,不可能多读/少读);下次再度一定是另一个的请求行。
????????????????
9.为什么今天发的请求有很多,为什么到达服务器先收的是第一行,有没有可能第一行卡在了网上,先收到的是第二行?应用层收到的永远是有序的,传输层不一定,有许多机制可以保证它的有序性。客户端发送第一行,第二行...服务器确实可能受到的是第二行,第一行...但对方向应用层交付的时候必须是第一行,第二行...因为数据乱序本身是可靠性的一种,必须保证按序到达,这个是有TCP保证的。HTTP压根不关心收到的数据变乱的问题。 ????????????????????????
|