什么网站做一手项目好,洛阳市河阳建设工程有限公司网站,wordpress获取自定义字段值,wordpress给文章设置标签应用层协议 ——— HTTP协议 HTTP简介认识URL二、登录信息三、服务器地址四、服务器端口号五、带层次的文件路径六、查询字符串七、片段标识符urlencode和urldecodeHTTP协议格式HTTP请求协议格式HTTP的方法HTTP的状态码HTTP常见的HeaderHTTPS VS HTTP对称加密 VS 非对称加密 HT… 应用层协议 ——— HTTP协议 HTTP简介认识URL二、登录信息三、服务器地址四、服务器端口号五、带层次的文件路径六、查询字符串七、片段标识符urlencode和urldecodeHTTP协议格式HTTP请求协议格式HTTP的方法HTTP的状态码HTTP常见的HeaderHTTPS VS HTTP对称加密 VS 非对称加密 HTTP简介
HTTPHyper Text Transfer Protocol协议又叫做超文本传输协议是一个简单的请求-响应协议HTTP通常运行在TCP之上。 在编写网络通信代码时我们可以自己进行协议的定制但实际有很多优秀的工程师早就已经写出了许多非常成熟的应用层协议其中最典型的就是HTTP协议。
认识URL
URLUniform Resource Lacator叫做统一资源定位符也就是我们通常所说的网址是因特网的万维网服务程序上用于指定信息位置的表示方法。 一、协议方案名 http://表示的是协议名称表示请求时需要使用的协议通常使用的是HTTP协议或安全协议HTTPS。HTTPS是以安全为目标的HTTP通道在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性。 常见的应用层协议
DNSDomain Name System协议域名系统。 FTPFile Transfer Protocol协议文件传输协议。 TELNETTelnet协议远程终端协议。 HTTPHyper Text Transfer Protocol协议超文本传输协议。 HTTPSHyper Text Transfer Protocol over SecureSocket Layer协议安全数据传输协议。 SMTPSimple Mail Transfer Protocol协议电子邮件传输协议。 POP3Post Office Protocol - Version 3协议邮件读取协议。 SNMPSimple Network Management Protocol协议简单网络管理协议。 TFTPTrivial File Transfer Protocol协议简单文件传输协议。
二、登录信息
usr:pass表示的是登录认证信息包括登录用户的用户名和密码。虽然登录认证信息可以在URL中体现出来但绝大多数URL的这个字段都是被省略的因为登录信息可以通过其他方案交付给服务器。
三、服务器地址
www.example.jp表示的是服务器地址也叫做域名比如www.alibaba.comwww.qq.comwww.baidu.com。
需要注意的是我们用IP地址标识公网内的一台主机但IP地址本身并不适合给用户看。比如说我们可以通过ping命令分别获得www.baidu.com和www.qq.com这两个域名解析后的IP地址。 如果用户看到的是这两个IP地址那么用户在访问这个网站之前并不知道这两个网站到底是干什么的但如果用户看到的是www.baidu.com和www.qq.com这两个域名那么用户至少知道这两个网站分别对应的是哪家公司因此域名具有更好的自描述性。
实际我们可以认为域名和IP地址是等价的在计算机当中使用的时候既可以使用域名也可以使用IP地址。但URL呈现出来是可以让用户看到的因此URL当中是以域名的形式表示服务器地址的。
四、服务器端口号
80表示的是服务器端口号。HTTP协议和套接字编程一样都是位于应用层的在进行套接字编程时我们需要给服务器绑定对应的IP和端口而这里的应用层协议也同样需要有明确的端口号。
常见协议对应的端口号
协议名称对应端口号HTTP80HTTPS443SSH22
当我们使用某种协议时该协议实际就是在为我们提供服务现在这些常用的服务与端口号之间的对应关系都是明确的所以我们在使用某种协议时实际是不需要指明该协议对应的端口号的因此在URL当中服务器的端口号一般也是被省略的。
五、带层次的文件路径
/dir/index.htm表示的是要访问的资源所在的路径。访问服务器的目的是获取服务器上的某种资源通过前面的域名和端口已经能够找到对应的服务器进程了此时要做的就是指明该资源所在的路径。
比如我们打开浏览器输入百度的域名后此时浏览器就帮我们获取到了百度的首页。 当我们发起网页请求时本质是获得了这样的一张网页信息然后浏览器对这张网页信息进行解释最后就呈现出了对应的网页。 我们可以将这种资源称为网页资源此外我们还会向服务器请求视频、音频、网页、图片等资源。HTTP之所以叫做超文本传输协议而不叫做文本传输协议就是因为有很多资源实际并不是普通的文本资源。
因此在URL当中就有这样一个字段用于表示要访问的资源所在的路径。此外我们可以看到这里的路径分隔符是/而不是\这也就证明了实际很多服务都是部署在Linux上的。
六、查询字符串
uid1表示的是请求时提供的额外的参数这些参数是以键值对的形式通过符号分隔开的。
比如我们在百度上面搜索HTTP此时可以看到URL中有很多参数而在这众多的参数当中有一个参数wdword表示的就是我们搜索时的搜索关键字wdHTTP。
七、片段标识符
ch1表示的是片段标识符是对资源的部分补充。
比如我们在看组图的时候URL当中就会出现片段标识符。
urlencode和urldecode
如果在搜索关键字当中出现了像/?:这样的字符由于这些字符已经被URL当作特殊意义理解了因此URL在呈现时会对这些特殊字符进行转义。
转义的规则如下
将需要转码的字符转为十六进制然后从右到左取4位不足4位直接处理每两位做一位前面加上%编码成%XY格式。 示例 比如当我们搜索C时由于加号在URL当中也是特殊符号而字符转为十六进制后的值就是0x2B因此一个就会被编码成一个%2B。 说明一下 URL当中除了会对这些特殊符号做编码对中文也会进行编码。
HTTP协议格式
应用层常见的协议有HTTP和HTTPS传输层常见的协议有TCP网络层常见的协议是IP数据链路层对应就是MAC帧了。其中下三层是由操作系统或者驱动帮我们完成的它们主要负责的是通信细节。如果应用层不考虑下三层在应用层自己的心目当中它就可以认为自己是在和对方的应用层在直接进行数据交互。 下三层负责的是通信细节而应用层负责的是如何使用传输过来的数据两台主机在进行通信的时候应用层的数据能够成功交给对端应用层因为网络协议栈的下三层已经负责完成了这样的通信细节而如何使用传输过来的数据就需要我们去定制协议这里最典型的就是HTTP协议。
HTTP是基于请求和响应的应用层服务作为客户端你可以向服务器发起request服务器收到这个request后会对这个request做数据分析得出你想要访问什么资源然后服务器再构建response完成这一次HTTP的请求。这种基于requestresponse这样的工作方式我们称之为cs或bs模式其中c表示clients表示serverb表示browser。
由于HTTP是基于请求和响应的应用层访问因此我们必须要知道HTTP对应的请求格式和响应格式这就是学习HTTP的重点。
HTTP请求协议格式
HTTP请求协议格式如下 HTTP请求由以下四部分组成
请求行[请求方法][url][http版本] 请求报头请求的属性这些属性都是以key: value的形式按行陈列的。 空行遇到空行表示请求报头结束。 请求正文请求正文允许为空字符串如果请求正文存在则在请求报头中会有一个Content-Length属性来标识请求正文的长度。 其中前面三部分是一般是HTTP协议自带的是由HTTP协议自行设置的而请求正文一般是用户的相关信息或数据如果用户在请求时没有信息要上传给服务器此时请求正文就为空字符串。 如何将HTTP请求的报头与有效载荷进行分离 当应用层收到一个HTTP请求时它必须想办法将HTTP的报头与有效载荷进行分离。对于HTTP请求来讲这里的请求行和请求报头就是HTTP的报头信息而这里的请求正文实际就是HTTP的有效载荷。
我们可以根据HTTP请求当中的空行来进行分离当服务器收到一个HTTP请求后就可以按行进行读取如果读取到空行则说明已经将报头读取完毕实际HTTP请求当中的空行就是用来分离报头和有效载荷的。
如果将HTTP请求想象成一个大的线性结构此时每行的内容都是用\n隔开的因此在读取过程中如果连续读取到了两个\n就说明已经将报头读取完毕了后面剩下的就是有效载荷了。 获取浏览器的HTTP请求 在网络协议栈中应用层的下一层叫做传输层而HTTP协议底层通常使用的传输层协议是TCP协议因此我们可以用套接字编写一个TCP服务器然后启动浏览器访问我们的这个服务器。
由于我们的服务器是直接用TCP套接字读取浏览器发来的HTTP请求此时在服务端没有应用层对这个HTTP请求进行过任何解析因此我们可以直接将浏览器发来的HTTP请求进行打印输出此时就能看到HTTP请求的基本构成。 因此下面我们编写一个简单的TCP服务器这个服务器要做的就是把浏览器发来的HTTP请求进行打印即可。
#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;close(sock);exit(0);}//爷爷进程close(sock);waitpid(-1, nullptr, 0); //等待爸爸进程}return 0;
}说明一下
浏览器向我们的服务器发起HTTP请求后因为我们的服务器没有对进行响应此时浏览器就会认为服务器没有收到然后再不断发起新的HTTP请求因此虽然我们只用浏览器访问了一次但会受到多次HTTP请求。 由于浏览器发起请求时默认用的就是HTTP协议因此我们在浏览器的url框当中输入网址时可以不用指明HTTP协议。 url当中的/不能称之为我们云服务器上根目录这个/表示的是web根目录这个web根目录可以是你的机器上的任何一个目录这个是可以自己指定的不一定就是Linux的根目录。 其中请求行当中的url一般是不携带域名以及端口号的因为在请求报头中的Host字段当中会进行指明请求行当中的url表示你要访问这个服务器上的哪一路径下的资源。如果浏览器在访问我们的服务器时指明要访问的资源路径那么此时浏览器发起的HTTP请求当中的url也会跟着变成该路径。 而请求报头当中全部都是以key: value形式按行陈列的各种请求属性请求属性陈列完后紧接着的就是一个空行空行后的就是本次HTTP请求的请求正文此时请求正文为空字符串因此这里有两个空行。
HTTP响应协议格式 HTTP响应协议格式如下 HTTP响应由以下四部分组成
状态行[http版本][状态码][状态码描述] 响应报头响应的属性这些属性都是以key: value的形式按行陈列的。 空行遇到空行表示响应报头结束。 响应正文响应正文允许为空字符串如果响应正文存在则响应报头中会有一个Content-Length属性来标识响应正文的长度。比如服务器返回了一个html页面那么这个html页面的内容就是在响应正文当中的。 如何将HTTP响应的报头与有效载荷进行分离 对于HTTP响应来讲这里的状态行和响应报头就是HTTP的报头信息而这里的响应正文实际就是HTTP的有效载荷。与HTTP请求相同当应用层收到一个HTTP响应时也是根据HTTP响应当中的空行来分离报头和有效载荷的。当客户端收到一个HTTP响应后就可以按行进行读取如果读取到空行则说明报头已经读取完毕。 构建HTTP响应给浏览器 服务器读取到客户端发来的HTTP请求后需要对这个HTTP请求进行各种数据分析然后构建成对应的HTTP响应发回给客户端。而我们的服务器连接到客户端后实际就只读取了客户端发来的HTTP请求就将连接断开了。
接下来我们可以构建一个HTTP请求给浏览器鉴于现在还没有办法分析浏览器发来的HTTP请求这里我们可以给浏览器返回一个固定的HTTP响应。我们就将当前服务程序所在的路径作为我们的web根目录我们可以在该目录下创建一个html文件然后编写一个简单的html作为当前服务器的首页。 当浏览器向服务器发起HTTP请求时不管浏览器发来的是什么请求我们都将这个网页响应给浏览器此时这个html文件的内容就应该放在响应正文当中我们只需读取该文件当中的内容然后将其作为响应正文即可。
#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; //响应报头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;
}因此当浏览器访问我们的服务器时服务器会将这个index.html文件响应给浏览器而该html文件被浏览器解释后就会显示出相应的内容。 说明一下
实际我们在进行网络请求的时候如果不指明请求资源的路径此时默认你想访问的就是目标网站的首页也就是web根目录下的index.html文件。 由于只是作为示例我们在构建HTTP响应时在响应报头当中只添加了一个属性信息Content-Length表示响应正文的长度实际HTTP响应报头当中的属性信息还有很多。 HTTP为什么要交互版本 HTTP请求当中的请求行和HTTP响应当中的状态行当中都包含了http的版本信息。其中HTTP请求是由客户端发的因此HTTP请求当中表明的是客户端的http版本而HTTP响应是由服务器发的因此HTTP响应当中表明的是服务器的http版本。
客户端和服务器双方在进行通信时会交互双方http版本主要还是为了兼容性的问题。因为服务器和客户端使用的可能是不同的http版本为了让不同版本的客户端都能享受到对应的服务此时就要求通信双方需要进行版本协商。
客户端在发起HTTP请求时告诉服务器自己所使用的http版本此时服务器就可以根据客户端使用的http版本为客户端提供对应的服务而不至于因为双方使用的http版本不同而导致无法正常通信。因此为了保证良好的兼容性通信双方需要交互一下各自的版本信息。
HTTP的方法
常用方法
方法说明支持的HTTP协议版本GET获取资源1.0、1.1POST传输实体主体1.0、1.1
GET方法一般用于获取某种资源信息而POST方法一般用于将数据上传给服务器。但实际我们上传数据时也有可能使用GET方法比如百度提交数据时实际使用的就是GET方法。
GET方法和POST方法都可以带参
GET方法是通过url传参的。 POST方法是通过正文传参的。 从GET方法和POST方法的传参形式可以看出POST方法能传递更多的参数因为url的长度是有限制的POST方法通过正文传参就可以携带更多的数据。
此外使用POST方法传参更加私密因为POST方法不会将你的参数回显到url当中此时也就不会被别人轻易看到。不能说POST方法比GET方法更安全因为POST方法和GET方法实际都不安全要做到安全只能通过加密来完成。
HTTP的状态码 最常见的状态码比如200OK404Not Found403Forbidden请求权限不够302Redirect504Bad Gateway。 Redirection重定向状态码 重定向就是通过各种方法将各种网络请求重新定个方向转到其它位置此时这个服务器相当于提供了一个引路的服务。
重定向又可分为临时重定向和永久重定向其中状态码301表示的就是永久重定向而状态码302和307表示的是临时重定向。
临时重定向和永久重定向本质是影响客户端的标签决定客户端是否需要更新目标地址。如果某个网站是永久重定向那么第一次访问该网站时由浏览器帮你进行重定向但后续再访问该网站时就不需要浏览器再进行重定向了此时你访问的直接就是重定向后的网站。而如果某个网站是临时重定向那么每次访问该网站时如果需要进行重定向都需要浏览器来帮我们完成重定向跳转到目标网站。 临时重定向演示 进行临时重定向时需要用到Location字段Location字段是HTTP报头当中的一个属性信息该字段表明了你所要重定向到的目标网站。
我们这里要演示临时重定向可以将HTTP响应当中的状态码改为307然后跟上对应的状态码描述此外还需要在HTTP响应报头当中添加Location字段这个Location后面跟的就是你需要重定向到的网页比如我们这里将其设置为CSDN的首页。
#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;//构建HTTP响应string status_line http/1.1 307 Temporary Redirect\n; //状态行string response_header Location: https://www.csdn.net/\n; //响应报头string blank \n; //空行string response status_line response_header blank; //响应报文//响应HTTP请求send(sock, response.c_str(), response.size(), 0);close(sock);exit(0);}//爷爷进程close(sock);waitpid(-1, nullptr, 0); //等待爸爸进程}return 0;
}
HTTP常见的Header
HTTP常见的Header如下
Content-Type数据类型text/html等。 Content-Length正文的长度。 Host客户端告知服务器所请求的资源是在哪个主机的哪个端口上。 User-Agent声明用户的操作系统和浏览器的版本信息。 Referer当前页面是哪个页面跳转过来的。 Location搭配3XX状态码使用告诉客户端接下来要去哪里访问。 Cookie用于在客户端存储少量信息通常用于实现会话session的功能。 Host Host字段表明了客户端要访问的服务的IP和端口比如当浏览器访问我们的服务器时浏览器发来的HTTP请求当中的Host字段填的就是我们的IP和端口。但客户端不就是要访问服务器吗为什么客户端还要告诉服务器它要访问的服务对应的IP和端口
因为有些服务器实际提供的是一种代理服务也就是代替客户端向其他服务器发起请求然后将请求得到的结果再返回给客户端。在这种情况下客户端就必须告诉代理服务器它要访问的服务对应的IP和端口此时Host提供的信息就有效了。 User-Agent User-Agent代表的是客户端对应的操作系统和浏览器的版本信息。
比如当我们用电脑下载某些软件时它会自动向我们展示与我们操作系统相匹配的版本这实际就是因为我们在向目标网站发起请求的时候User-Agent字段当中包含了我们的主机信息此时该网站就会向你推送相匹配的软件版本。 Referer Referer代表的是你当前是从哪一个页面跳转过来的。Referer记录上一个页面的好处一方面是方便回退另一方面可以知道我们当前页面与上一个页面之间的相关性。 Keep-Alive长连接 HTTP/1.0是通过requestresponse的方式来进行请求和响应的HTTP/1.0常见的工作方式就是客户端和服务器先建立链接然后客户端发起请求给服务器服务器再对该请求进行响应然后立马端口连接。
但如果一个连接建立后客户端和服务器只进行一次交互就将连接关闭就太浪费资源了因此现在主流的HTTP/1.1是支持长连接的。所谓的长连接就是建立连接后客户端可以不断的向服务器一次写入多个HTTP请求而服务器在上层依次读取这些请求就行了此时一条连接就可以传送大量的请求和响应这就是长连接。
如果HTTP请求或响应报头当中的Connect字段对应的值是Keep-Alive就代表支持长连接。 Cookie和Session HTTP实际上是一种无状态协议HTTP的每次请求/响应之间是没有任何关系的但你在使用浏览器的时候发现并不是这样的。
比如当你登录一次CSDN后就算你把CSDN网站关了甚至是重启电脑当你再次打开CSDN网站时CSDN并没有要求你再次输入账号和密码这实际上是通过cookie技术实现的点击浏览器当中锁的标志就可以看到对应网站的各种cookie数据。 这些cookie数据实际都是对应的服务器方写的如果你将对应的某些cookie删除那么此时可能就需要你重新进行登录认证了因为你删除的可能正好就是你登录时所设置的cookie信息。 cookie是什么呢 因为HTTP是一种无状态协议如果没有cookie的存在那么每当我们要进行页面请求时都需要重新输入账号和密码进行认证这样太麻烦了。
比如你是某个视频网站的VIP这个网站里面的VIP视频有成百上千个你每次点击一个视频都要重新进行VIP身份认证。而HTTP不支持记录用户状态那么我们就需要有一种独立技术来帮我们支持这种技术目前现在已经内置到HTTP协议当中了叫做cookie。
当我们第一次登录某个网站时需要输入我们的账号和密码进行身份认证此时如果服务器经过数据比对后判定你是一个合法的用户那么为了让你后续在进行某些网页请求时不用重新输入账号和密码此时服务器就会进行Set-Cookie的设置。Set-Cookie也是HTTP报头当中的一种属性信息
当认证通过并在服务端进行Set-Cookie设置后服务器在对浏览器进行HTTP响应时就会将这个Set-Cookie响应给浏览器。而浏览器收到响应后会自动提取出Set-Cookie的值将其保存在浏览器的cookie文件当中此时就相当于我的账号和密码信息保存在本地浏览器的cookie文件当中。
从第一次登录认证之后浏览器再向该网站发起的HTTP请求当中就会自动包含一个cookie字段其中携带的就是我第一次的认证信息此后对端服务器需要对你进行认证时就会直接提取出HTTP请求当中的cookie字段而不会重新让你输入账号和密码了。
也就是在第一次认证登录后后续所有的认证都变成了自动认证这就叫做cookie技术。 内存级别文件级别 cookie就是在浏览器当中的一个小文件文件里记录的就是用户的私有信息。cookie文件可以分为两种一种是内存级别的cookie文件另一种是文件级别的cookie文件。
将浏览器关掉后再打开访问之前登录过的网站如果需要你重新输入账号和密码说明你之前登录时浏览器当中保存的cookie信息是内存级别的。 将浏览器关掉甚至将电脑重启再打开访问之前登录过的网站如果不需要你重新输入账户和密码说明你之前登录时浏览器当中保存的cookie信息是文件级别的。 cookie被盗 如果你浏览器当中保存的cookie信息被非法用户盗取了那么此时这个非法用户就可以用你的cookie信息以你的身份去访问你曾经访问过的网站我们将这种现象称为cookie被盗取了。
比如你不小心点了某个链接这个链接可能就是一个下载程序当你点击之后它就会通过某种方式把程序下载到你本地并且自动执行该程序该程序会扫描你的浏览器当中的cookie目录把所有的cookie信息通过网络的方式传送给恶意方当恶意方拿到你的cookie信息后就可以拷贝到它的浏览器对应的cookie目录当中然后以你的身份访问你曾经访问过的网站。 SessionID 单纯的使用cookie是非常不安全的因为此时cookie文件当中就保存的是你的私密信息一旦cookie文件泄漏你的隐私信息也就泄漏。
所以当前主流的服务器还引入了SessionID这样的概念当我们第一次登录某个网站输入账号和密码后服务器认证成功后还会服务端生成一个对应的SessionID这个SessionID与用户信息是不相关的。系统会将所有登录用户的SessionID值统一维护起来。
此时当认证通过后服务端在对浏览器进行HTTP响应时就会将这个生成的SessionID值响应给浏览器。浏览器收到响应后会自动提取出SessionID的值将其保存在浏览器的cookie文件当中。后续访问该服务器时对应的HTTP请求当中就会自动携带上这个SessionID。 而服务器识别到HTTP请求当中包含了SessionID就会提取出这个SessionID然后再到对应的集合当中进行对比对比成功就说明这个用户是曾经登录过的此时也就自动就认证成功了然后就会正常处理你发来的请求这就是我们当前主流的工作方式。 安全是相对的 引入SessionID之后浏览器当中的cookie文件保存的是SessionID此时这个cookie文件同样可能被盗取。此时用户的账号和密码虽然不会泄漏了但用户对应的SessionID是会泄漏的非法用户仍然可以盗取我的SessionID去访问我曾经访问过的服务器相当于还是存在刚才的问题。
之前的工作方式就相当于把账号和密码信息在浏览器当中再保存一份每次请求时都自动将账号和密码的信息携带上但是账号和密码一直在网当中发送太不安全了。 因此现在的工作方式是服务器只有在第一次认证的时候需要在网络中传输账号和密码此后在网络上发送的都是SessionID。 这种方法虽然没有真正解决安全问题但这种方法是相对安全的。互联网上是不存在绝对安全这样的概念的任何安全都是相对的就算你将发送到网络当中的信息进行加密也有可能被别人破解。 不过在安全领域有一个准则如果破解某个信息的成本已经远远大于破解之后获得的收益说明做这个事是赔本的那么就可以说这个信息是安全的。 引入SessionID后的好处 在引入SessionID之前用户登录的账号信息都是保存在浏览器内部的此时的账号信息是由客户端去维护的。 而引入SessionID后用户登录的账号信息是有服务器去维护的在浏览器内部保存的只是SessionID。 此时虽然SessionID可能被非法用户盗取但服务器也可以使用各种各样的策略来保证用户账号的安全。
IP是有归类的可以通过IP地址来判断登录用户所在的地址范围。如果一个账号在短时间内登录地址发送了巨大变化此时服务器就会立马识别到这个账号发生异常了进而在服务器当中清除对应的SessionID的值。这时当你或那个非法用户想要访问服务器时就都需要重新输入账号和密码进行身份认证而只有你是知道自己的密码的当你重新认证登录后服务器就可以将另一方识别为非法用户进而对该非法用户进行对应的黑名单/白名单认证。 当操作者想要进行某些高权限的操作时会要求操作者再次输入账号和密码信息再次确认身份。就算你的账号被非法用户盗取了但非法用户在改你密码时需要输入旧密码这是非法用户在短时间内无法做到的因为它并不知道你的密码。这也就是为什么账号被盗后还可以找回来的原因因为非法用户无法在短时间内修改你的账号密码此时你就可以通过追回的方式让当前的SessionID失效让使用该账号的用户进行重新登录认证。 SessionID也有过期策略比如SessionID是一个小时内是有效的。所以即便你的SessionID被非法用户盗取了也仅仅是在一个小时内有效而且在功能上受约束所以不会造成太大的影响。 任何事情都有两面性如果不是这些非法用户的存在现在的服务器肯定是漏洞百出只有双方不断进行对抗双方才能不断进步。
HTTPS VS HTTP
早期很多公司刚起步的时候使用的应用层协议都是HTTP而HTTP无论是用GET方法还是POST方法传参都是没有经过任何加密的因此早期很多的信息都是可以通过抓包工具抓到的。
为了解决这个问题于是出现了HTTPS协议HTTPS实际就是在应用层和传输层协议之间加了一层加密层SSLTLS这层加密层本身也是属于应用层的它会对用户的个人信息进行各种程度的加密。HTTPS在交付数据时先把数据交给加密层由加密层对数据加密后再交给传输层。
当然通信双方使用的应用层协议必须是一样的因此对端的应用层也必须使用HTTPS当对端的传输层收到数据后会先将数据交给加密层由加密层对数据进行解密后再将数据交给应用层。 此时数据只有在用户层应用层是没有被加密的而在应用层往下以及网络当中都是加密的这就叫做HTTPS。
对称加密 VS 非对称加密
加密的方式可以分为对称加密和非对称加密
采用单钥密码系统的加密方法同一个密钥可以同时用作信息的加密和解密这种加密方法称为对称加密。 采用公钥和私钥来进行加密和解密用其中一个密钥进行加密就必须用另一个密钥进行解密这种加密方法称为非对称加密。 一般而言对称加密的效率比非对称加密的效率高。 对称加密的过程 对称加密的效率更高因此双方在进行正常通信时使用的是对称加密。但双方要进行对称加密通信此时就要去加密方要把密钥给解密方此时解密方才能对数据进行解密但加密方把密钥密钥也是数据给解密方时也是需要对密钥进行加密的解密废没法解密就没法拿到密钥这就变成了鸡生蛋蛋生鸡的问题了。
这里也不可能让加密方给密钥的时候不进行加密因为那样全世界都知道这个密钥了后续加密方的加密也就没有意义了。因此刚开始在进行密钥协商的时候需要用非对称加密。
对称加密的建立过程如下
通信双方建立连接的时候双方就可以把支持的加密算法作协商协商之后在服务器端形成非对称加密时使用的公钥和私钥在客户端形成对称加密时使用的密钥。 然后服务器将公钥交给客户端这个公钥全世界都可以看到然后客户端用这个公钥对客户端形成的密钥进行加密将加密后的密钥发送给服务器服务器拿到后再用它的私钥进行解密最终服务器就拿到了客户端的密钥。 这时客户端和服务器都有了这个密钥并且其他人是不知道的此时客户端和服务器就可以进行对称加密通信了。 需要注意的是这里客户端用公钥加密后的密钥只有服务器能够解密因为在非对称加密当中数据用公钥加密就必须用私钥解密而只有服务器才有私钥其他人都只有公钥。