1、http協(xié)議
在之前學(xué)習(xí)序列化和反序列化的時(shí)候,認(rèn)識(shí)到主機(jī)之間傳輸結(jié)構(gòu)數(shù)據(jù)的時(shí)候,最好是通過(guò)某種約定將結(jié)構(gòu)數(shù)據(jù)序列化成一串字符串,接收方再通過(guò)反序列化將字符串轉(zhuǎn)換成結(jié)構(gòu)數(shù)據(jù)。以上說(shuō)的這種約定,其實(shí)可以看成是用戶層通信的一種協(xié)議,是由程序猿自己定的。
?
實(shí)際上,已經(jīng)有很多大佬寫了很多很好的應(yīng)用層上的協(xié)議供我們參考學(xué)習(xí)。http協(xié)議(超文本傳輸協(xié)議)就是其中一個(gè)。
?
1.1 認(rèn)識(shí)URL
早期的網(wǎng)址是用http協(xié)議的,不過(guò)經(jīng)過(guò)長(zhǎng)時(shí)間的技術(shù)發(fā)展后,目前網(wǎng)址一般都是用https協(xié)議的。
不過(guò)得先認(rèn)識(shí)http,這樣才能更好了解https。
?
下面就是一種網(wǎng)址格式。
實(shí)際上,目前的URL普遍省略了以下部分:
登錄信息(一般都用一個(gè)可以互動(dòng)的窗口讓用戶填寫)
端口號(hào)(端口號(hào)被缺省了,因?yàn)槊總€(gè)協(xié)議所有的端口號(hào)被固定了,比如http:80,https:443)
那么URL究竟是個(gè)什么呢?
URL(uniform Resource Locator)又被稱為統(tǒng)一資源定位符,顧名資源定位符,在互聯(lián)網(wǎng)上用來(lái)標(biāo)識(shí)和定位資源的一種文本字符串。URL可以幫助我們快速定位到網(wǎng)絡(luò)上的不同資源。(比如網(wǎng)頁(yè)、圖片、視頻等)
?
URL如何做到?
在URL中,http協(xié)議指定了如何訪問(wèn)資源,服務(wù)器地址(也稱域名,域名是可以轉(zhuǎn)換成IP地址的)標(biāo)識(shí)了互聯(lián)網(wǎng)上主機(jī)的唯一性,因此再通過(guò)特定端口,就可以訪問(wèn)到特定的服務(wù)端進(jìn)行連接。可以看到URL上還有帶層次的文件路徑,沒(méi)錯(cuò),服務(wù)端一般是在Linux系統(tǒng)上搭建的,這就是需要訪問(wèn)的linux服務(wù)器的資源文件路徑。
值得注意的是,這個(gè)文件路徑不是簡(jiǎn)單的在服務(wù)器上的絕對(duì)路徑的,而是大多數(shù)情況下,服務(wù)端進(jìn)程(Web服務(wù)器)會(huì)將請(qǐng)求的URL映射到服務(wù)端的文件系統(tǒng)路徑。例如,如果基礎(chǔ)路徑是服務(wù)端上的目錄/wwwroot,請(qǐng)求的URL是“index.html”,那么請(qǐng)求的資源文件路徑就是/wwwroot/index.html。
?
urlencode和urldecode
可以看到像/ ? : 這樣的字符在URL中有特殊的含義,為了不讓這些字符隨意出現(xiàn),如果參數(shù)中要有一些特殊字符就需要通過(guò)urlencode進(jìn)行轉(zhuǎn)義。
一些網(wǎng)站對(duì)于中文,也會(huì)進(jìn)行轉(zhuǎn)義,比如在bing中搜索C++,就變成了C%2B%2B。
unldecode就是逆過(guò)程。
轉(zhuǎn)義的規(guī)則如下: 將需要轉(zhuǎn)碼的字符轉(zhuǎn)為16進(jìn)制,然后從右到左,取4位(不足4位直接處理),每2位做一位,前面加上%,編碼成%XY格式(比如‘+’的ASCII碼是43,對(duì)應(yīng)16進(jìn)制就是2B)
?
1.2 http協(xié)議格式
http在被設(shè)計(jì)的時(shí)候也有著自己的格式。
任何協(xié)議的請(qǐng)求或接受都是報(bào)頭+有效載荷。
其中請(qǐng)求部分
- \r\n就是一個(gè)約定分隔符,代表每一行的結(jié)束。
- 請(qǐng)求報(bào)頭中有著一些屬性(具體的下面說(shuō)),有效載荷中代表一些用戶和服務(wù)端的交互數(shù)據(jù)。(比如登錄信息、Up主上傳的音頻、視頻)
- 讀取完整報(bào)頭時(shí)按行讀取直到讀取空行,空行的作用就是能代表報(bào)頭讀取完畢,接下來(lái)就是有效載荷部分。
- 如何保證讀完正文呢? 在報(bào)頭中有一個(gè)記錄正文長(zhǎng)度的屬性Content-Length。
?其中響應(yīng)方
- http常用版本是http1.0和http1.1,可以看到客戶端和服務(wù)端都有自己的版本,這也是為了服務(wù)端能根據(jù)版本信息去適配低版本客戶端而有的。
- 狀態(tài)碼和狀態(tài)碼描述,可以代表響應(yīng)的情況。(比如訪問(wèn)網(wǎng)頁(yè)的404錯(cuò)誤碼和錯(cuò)誤信息)
- 響應(yīng)正文就是客戶端需要拿到的資源。
?
下面通過(guò)一個(gè)在傳輸層以TCP協(xié)議傳輸?shù)拇a來(lái)體會(huì)一下。
#include <iostream>
#include <string>
#include <string.h>
#include <fstream>
#include <sys/socket.h>
#include <assert.h>
#include <stdarg.h>
#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <pthread.h>
using namespace std;
#define CRLF "\r\n"
#define SPACE " "
#define SPACE_LEN strlen(SPACE)
#define HOME_PAGE "index.html"
#define ROOT_PATH "wwwroot"
std::string getPath(std::string http_request)
{
std::size_t pos = http_request.find(CRLF);
if(pos == std::string::npos) return "";
std::string request_line = http_request.substr(0, pos);
//GET /a/b/c http/1.1
std::size_t first = request_line.find(SPACE);
if(pos == std::string::npos) return "";
std::size_t second = request_line.rfind(SPACE);
if(pos == std::string::npos) return "";
std::string path = request_line.substr(first+SPACE_LEN, second - (first+SPACE_LEN));
//當(dāng)url為/時(shí),不能代表獲得全部資源,而是類似主頁(yè)的index
if(path.size() == 1 && path[0] == '/') path += HOME_PAGE;
return path;
}
std::string readFile(const std::string &recource)
{
std::ifstream in(recource, std::ifstream::binary);
if(!in.is_open()) return "404";
std::string content;
std::string line;
while(std::getline(in, line)) content += line;
in.close();
return content;
}
//http的請(qǐng)求 {method} 路徑 版本
void handlerHttpRequest(int sock)
{
//讀取發(fā)送方信息
char buffer[10240];
ssize_t s = read(sock, buffer, sizeof buffer);
if(s > 0) cout << buffer;
//開始響應(yīng)
//獲得資源在服務(wù)端下的地址
std::string path = getPath(buffer);
std::string recource = ROOT_PATH;
recource += path;
std::cout << recource << std::endl;
//讀取html資源(前端代碼)
std::string html = readFile(recource);
//http響應(yīng)方
std::string response;
//報(bào)頭
response = "HTTP/1.0 200 OK\r\n";
response += "Content-Type: text/html\r\n";
response += ("Content-Length: " + std::to_string(html.size()) + "\r\n");
response += "Set-Cookie: this is my cookie content;\r\n";
//空行
response += "\r\n";
//回應(yīng)正文
response += html;
//發(fā)送給客戶端
send(sock, response.c_str(), response.size(), 0);
}
class tcpServer
{
public:
tcpServer() :_listenSock(-1), _quit(false)
{}
tcpServer(uint16_t port, const std::string& ip = "")
:_listenSock(-1)
,_serverPort(port)
,_serverIp(ip)
,_quit(false)
{}
~tcpServer()
{
if(_listenSock >= 0)
close(_listenSock);
}
void init()
{
//1、創(chuàng)建套接字
_listenSock = socket(AF_INET, SOCK_STREAM, 0);
if(_listenSock < 0)
{
exit(1);
}
//2、bind服務(wù)器信息
//2.1 填充服務(wù)器信息
struct sockaddr_in server;
//類似memset 清0
bzero(&server, sizeof(server));
//填寫協(xié)議簇
server.sin_family = PF_INET;
//填寫端口 因?yàn)槭窍蚓W(wǎng)絡(luò)中傳輸,所以要進(jìn)行網(wǎng)絡(luò)字節(jié)序的轉(zhuǎn)換
server.sin_port = htons(_serverPort);
//填寫IP 如果ip為空,設(shè)置為INADDR_ANY, 系統(tǒng)會(huì)幫忙填寫
server.sin_addr.s_addr = _serverIp.empty() ? INADDR_ANY : inet_addr(_serverIp.c_str());
//2.2 bind 綁定
if(bind(_listenSock, (const struct sockaddr*)&server, sizeof(server)) < 0)
{
exit(2);
}
//3、監(jiān)聽 獲取連接 因?yàn)閠cp是需要建立連接的,這一步相當(dāng)于等待客戶端請(qǐng)求連接
if(listen(_listenSock, 5) < 0)
{
exit(3);
}
}
void start()
{
while(!_quit)
{
//4.建立連接
//客戶端信息
struct sockaddr_in peer;
socklen_t peerLen = sizeof(peer);
//accept返回一個(gè)文件描述符
//_listenSock用來(lái)尋找連接
//serviceSock用來(lái)建立連接
//accept 將一個(gè)輸出新參數(shù)傳入,運(yùn)行完后接收
int serviceSock = accept(_listenSock, (struct sockaddr*)&peer, &peerLen);
if(_quit)
{
break;
}
if(serviceSock < 0)
{
exit(4);
}
//至此服務(wù)器和客戶端的連接建立完成
//5.獲取客戶端信息
//獲取客戶端ip
std::string peerIp = inet_ntoa(peer.sin_addr);
uint16_t peerPort = ntohs(peer.sin_port);
signal(SIGCHLD, SIG_IGN);
if(fork() == 0)
{
close(_listenSock);
handlerHttpRequest(serviceSock);
exit(0);
}
close(serviceSock);
}
}
void quitServer()
{
_quit = true;
}
private:
//監(jiān)聽套接字
int _listenSock;
//端口
uint16_t _serverPort;
//ip
std::string _serverIp;
//安全退出
bool _quit;
};
static void Usage(const std::string& proc)
{
std::cout << "Usage:\t\n" << proc << " port : ip" << std::endl;
}
int main(int argc, char* argv[])
{
if(argc != 2 && argc != 3)
{
Usage(argv[0]);
exit(0);
}
std::string serviceIp;
uint16_t servicePort;
if(argc == 2)
{
servicePort = atoi(argv[1]);
}
if(argc == 3)
{
serviceIp = argv[2];
}
tcpServer ts(servicePort, serviceIp);
ts.init();
ts.start();
return 0;
}
前端測(cè)試代碼
基礎(chǔ)路徑是服務(wù)端前提下:/wwwroot/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>測(cè)試</title>
</head>
<body>
<h3>hello my server!</h3>
<p>我終于測(cè)試完了我的代碼</p>
<form action="/a/b/c.html" method="get">
Username: <input type="text" name="user"><br>
Password: <input type="password" name="passwd"><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
運(yùn)行代碼,通過(guò)瀏覽器輸入IP和端口讓瀏覽器以客戶端的方式向服務(wù)端發(fā)送以下信息。
?
服務(wù)端收到數(shù)據(jù)以后,向客戶端響應(yīng),就讀取了對(duì)應(yīng)的前端html代碼。
?
?
Linux下的telnet命令
telnet命令,能夠通過(guò)遠(yuǎn)程的,以協(xié)議方式登錄某種服務(wù)。
當(dāng)出現(xiàn)^],就說(shuō)明連接成功,就可以通過(guò)ctrl+] 然后回車,輸入請(qǐng)求行信息,就可以獲取響應(yīng)端報(bào)頭和有效載荷內(nèi)容。
?
1.3 http的方法(GET和POST)
因?yàn)镠TTP其它的方法不太常用。
這里只具體說(shuō)GET和POST。
?
GET方法
可以注意到,在之前的前端代碼中。method就是get。
method="get"
還是上面那個(gè)代碼,在響應(yīng)網(wǎng)站中輸入賬號(hào)和密碼后,會(huì)發(fā)現(xiàn)一個(gè)這樣的現(xiàn)象。
首先,404錯(cuò)誤的出現(xiàn)肯定不是重點(diǎn),因?yàn)槲业拇a沒(méi)有提供確認(rèn)按鈕請(qǐng)求之后的響應(yīng)。重點(diǎn)是這次URL中,賬號(hào)和密碼竟然出現(xiàn)在了參數(shù)部分。
是的,http中GET方法提交參數(shù),會(huì)以明文的方式將我們對(duì)應(yīng)的參數(shù),拼接在URL中。
POST方法
其它都一樣,只將method改為post。
method="post"
可以看到提交的參數(shù)放到了正文中。
?
GET和POST的比較
- GET通過(guò)URL傳參,POST通過(guò)正文傳參。
- GET方法傳參不私密直接暴露出來(lái),POST正文傳參相對(duì)比較私密。(但是都不安全,通過(guò)抓包非常容易能得到)
- GET方法傳參一般傳小數(shù)據(jù),一般一些比較大的內(nèi)容都通過(guò)POST方式傳(文件、電影)
?
1.4 狀態(tài)碼
這里只關(guān)注這幾個(gè)常見(jiàn)的和常用的
200代表客戶端響應(yīng)成功。
當(dāng)因?yàn)榭蛻舳隋e(cuò)誤時(shí),會(huì)有404(Not Found)無(wú)法訪問(wèn),403(Forbidden)禁止訪問(wèn)。
當(dāng)服務(wù)器錯(cuò)誤,會(huì)有504(bad gateway),錯(cuò)誤的網(wǎng)關(guān)。?
較為重要的是3XX重定向狀態(tài)碼。其中有301永久重定向和302臨時(shí)重定向。
?
HTTP常見(jiàn)Header
- Content-Type: 數(shù)據(jù)類型(text/html等)
- Content-Length: Body的長(zhǎng)度
- Host: 客戶端告知服務(wù)器, 所請(qǐng)求的資源是在哪個(gè)主機(jī)的哪個(gè)端口上;
- User-Agent: 聲明用戶的操作系統(tǒng)和瀏覽器版本信息;(這個(gè)可以用在,比如用戶在下載網(wǎng)頁(yè)的時(shí)候,可以通過(guò)對(duì)不同的OS類型,率先提供匹配的下載版本。)
- referer: 當(dāng)前頁(yè)面是從哪個(gè)頁(yè)面跳轉(zhuǎn)過(guò)來(lái)的;
- location: 搭配3xx狀態(tài)碼使用, 告訴客戶端接下來(lái)要去哪里訪問(wèn);
- Cookie: 用于在客戶端存儲(chǔ)少量信息. 通常用于實(shí)現(xiàn)會(huì)話(session)的功能;
?
重定向狀態(tài)碼
對(duì)應(yīng)服務(wù)端兩者每什么區(qū)別,區(qū)別是在客戶端上的。
301:永久重定向,比如一個(gè)擁有很多客戶的舊網(wǎng)站需要關(guān)閉更換新的網(wǎng)站,那么就可以通過(guò)這個(gè)永久重定向跳轉(zhuǎn)到新的網(wǎng)站。這就需要客戶記住新的網(wǎng)站,不過(guò)現(xiàn)在有些瀏覽器會(huì)記錄經(jīng)常訪問(wèn)的網(wǎng)站。
302:臨時(shí)重定向,比如一些服務(wù)要升級(jí),就可以臨時(shí)重定向到一個(gè)新的網(wǎng)站,這個(gè)拷貝之前舊的服務(wù),當(dāng)服務(wù)升級(jí)完成后,就可以關(guān)閉這個(gè)臨時(shí)重定向。這對(duì)客戶不影響。
直接通過(guò)代碼演示,將上述代碼的處理函數(shù)改為以下。
void handlerHttpRequest(int sock)
{
//讀取發(fā)送方信息
char buffer[10240];
ssize_t s = read(sock, buffer, sizeof buffer);
if(s > 0) cout << buffer;
std::string response = "http/1.0 302 Movedtemporatily\r\n";
//填寫location屬性
response += "Location: https://blog.csdn.net/Ahaooooooo\r\n";
response += "\r\n";
send(sock, response.c_str(), response.size(), 0);
}
通過(guò)瀏覽器輸入ip:端口,結(jié)果也是成功返回到我的主頁(yè)
?
1.5 cookie
其實(shí)http協(xié)議有一個(gè)特點(diǎn)是無(wú)狀態(tài)。也就是http沒(méi)有記錄,要什么給什么。
?
不過(guò)我們經(jīng)常會(huì)看到一個(gè)現(xiàn)象,就是我們登錄網(wǎng)站時(shí),在填寫一次登錄信息后,不管是關(guān)瀏覽器還是關(guān)機(jī)。下一次再登錄網(wǎng)站時(shí),就默認(rèn)是登錄狀態(tài)了。這明顯不符合http的特點(diǎn)。其實(shí)就是cookie策略在幫助記錄的。
?
還是通過(guò)最開始的代碼運(yùn)行。
通過(guò)網(wǎng)站訪問(wèn)可以看到,cookie就是瀏覽器維護(hù)的文件,真正存在磁盤或者是一種內(nèi)存級(jí)文件(這也符合那種關(guān)閉瀏覽器就需要重新登錄的)
?
cookie的安全性問(wèn)題
上述討論簡(jiǎn)單傳文件的是在http1.0中較為常見(jiàn)的。如果一些惡意軟件將cookie軟件找到,那么里面看到的就是裸露的數(shù)據(jù),這就會(huì)造成安全性問(wèn)題。(cookie這種機(jī)制也不止運(yùn)用在瀏覽器,也會(huì)在一些軟件中。)
因此現(xiàn)在主流的都是一種cookie+session的方案。
這讓信息只放到了服務(wù)端,由產(chǎn)品公司進(jìn)行保護(hù),而公司相對(duì)于客戶的安全能力肯定是更高的。
?
1.6 短連接和長(zhǎng)連接
http在不同版本有不同的連接方式,在對(duì)應(yīng)屬性中有Connection字段,代表著不同連接。
http 1.0: closed 意為連接后響應(yīng)一次就關(guān)閉對(duì)應(yīng)文件描述符。
http 1.1: keep-alive 意為保持長(zhǎng)連接,不用總是連接完再斷開。
用戶所看到的完整網(wǎng)頁(yè)內(nèi)容,背后可能是無(wú)數(shù)次http請(qǐng)求。http主流底層采用的是TCP協(xié)議!如果采用短連接,那么在底層tcp就會(huì)不斷的進(jìn)行3次握手和四次揮手(可以理解為連接和斷開),這就會(huì)出現(xiàn)低效率問(wèn)題。
?
長(zhǎng)連接,對(duì)于多個(gè)請(qǐng)求訪問(wèn),在一次連接時(shí)就可以都收到,并且為了防止出現(xiàn)順序問(wèn)題,也會(huì)通過(guò)一種Pipeline技術(shù),使得依次響應(yīng)。
其實(shí)http是無(wú)連接的,它只是借助了tcp建立連接的功能。因此http被稱為一個(gè)超文本傳輸協(xié)議,是一個(gè)無(wú)狀態(tài)無(wú)連接的應(yīng)用層協(xié)議。
?
2、https協(xié)議
http因?yàn)槠鋫鬏敂?shù)據(jù)都是以明文方式進(jìn)行傳輸?shù)?,因此在傳輸?shù)倪^(guò)程中,是極有可能被第三方通過(guò)一些手段獲取或更改數(shù)據(jù),而造成數(shù)據(jù)安全問(wèn)題的。
https通過(guò)在http的基礎(chǔ)上添加了一層軟件層:SSL/TLS加密協(xié)議,使得數(shù)據(jù)在傳輸?shù)臅r(shí)候具有一定安全性。
http默認(rèn)端口是80,https默認(rèn)端口是443。
因此它們兩個(gè)是兩個(gè)不同的服務(wù)。
那么是不是https可以直接取代http了?
并不是,https因?yàn)樾枰用芙饷艿拇嬖?,肯定?huì)導(dǎo)致效率更低的問(wèn)題。因此在一些比較安全同時(shí)看重效率的場(chǎng)景下,http還是很有用的。
?
2.1 常見(jiàn)的加密方式
首先一個(gè)明文通過(guò)一個(gè)密鑰的轉(zhuǎn)換,就稱為了一個(gè)密文。
?
對(duì)稱加密: 采用單鑰密碼系統(tǒng)加密的方式,可同時(shí)用作信息加密和解密。(比如按位與 a^key = b, b^key = a),它的特點(diǎn)是計(jì)算量小,加密效率高。
非對(duì)稱加密: 需要兩個(gè)密鑰來(lái)加密和解密。兩個(gè)密鑰分別是公鑰和私鑰。
用法除了正著用也可以反著用。它的特點(diǎn)是算法越復(fù)雜,安全性越高。因此相對(duì)于對(duì)稱加密,加密速度非常慢。
?
數(shù)據(jù)摘要(也稱數(shù)據(jù)指紋): 原理是將數(shù)據(jù)通過(guò)一種單向散列函數(shù)(Hash函數(shù))生成一串固定的長(zhǎng)度的數(shù)據(jù)摘要。數(shù)據(jù)摘要不是一種加密算法,而是用來(lái)判斷數(shù)據(jù)有沒(méi)有被篡改。
?
數(shù)字簽名: 數(shù)據(jù)摘要通過(guò)加密就得到了數(shù)字簽名。(這個(gè)下面講)
?
2.2 探究https協(xié)議的加密
因?yàn)閿?shù)據(jù)安全問(wèn)題,數(shù)據(jù)應(yīng)該在加密之后以密文的方式在網(wǎng)絡(luò)中進(jìn)行傳輸,那么具體的方案,應(yīng)該是什么樣的呢?
方案一:只使用對(duì)稱加密
?
方案二:只使用非對(duì)稱加密
K代表公鑰,K’代表私鑰
?
方案三:只使用非對(duì)稱加密
并且,前面說(shuō)過(guò)非對(duì)稱加密是非常影響效率的,因此如果考慮效率,這個(gè)方案也是絕對(duì)不行的。
?
方案四:非對(duì)稱加密+對(duì)稱加密
第四個(gè)方案,其實(shí)效率問(wèn)題已經(jīng)解決了,但是還是有密鑰在傳輸?shù)倪^(guò)程中被第三方篡改的問(wèn)題。為了解決這個(gè)問(wèn)題,就需要下面一個(gè)方案。
?
2.3 CA證書
服務(wù)器在使用https之前,需要向CA機(jī)構(gòu)申領(lǐng)一份CA數(shù)字證書,數(shù)字證書里面含有證書申請(qǐng)者信息、公鑰信息等。服務(wù)端將證書傳給瀏覽器,瀏覽器從其中拿去公鑰。證書像是一個(gè)服務(wù)端公鑰的身份證,證明其權(quán)威性。
?
申請(qǐng)證書時(shí),需要在特定的平臺(tái)生成,并且會(huì)給一對(duì)密鑰,也就是公鑰和私鑰,其中公鑰會(huì)隨著CA證書交給客戶端,服務(wù)端自己保存私鑰。
?
當(dāng)服務(wù)端申請(qǐng)CA證書的時(shí)候,CA機(jī)構(gòu)會(huì)對(duì)該服務(wù)端進(jìn)行審核,并且為該網(wǎng)站形成數(shù)字簽名,具體過(guò)程如下:
- CA機(jī)構(gòu)有非對(duì)稱的公鑰A和私鑰A’
- CA機(jī)構(gòu)將證書的明文數(shù)據(jù)通過(guò)Hash函數(shù),形成數(shù)據(jù)摘要。
- 數(shù)據(jù)摘要通過(guò)私鑰加密就得到一個(gè)簽名S,附加到數(shù)據(jù)上就成了數(shù)字證書,就可以頒發(fā)給服務(wù)端了。
方案五:CA證書+非對(duì)稱加密+對(duì)稱加密
首先在傳輸CA證書的過(guò)程中,中間人是可以獲得CA證書的,也可以對(duì)其修改,但這是沒(méi)有用的。
因?yàn)樵贑lient收到證書時(shí),需要通過(guò)Hash函數(shù)將證書明文轉(zhuǎn)換成散列值和通過(guò)證書公鑰解密的數(shù)字簽名進(jìn)行比對(duì),如果不同就說(shuō)明出了問(wèn)題,就能察覺(jué)的到。
中間人也無(wú)法偽造證書,因?yàn)槠渲猩婕傲朔?wù)端的信息。
總結(jié):超文本傳輸http協(xié)議解決了客戶端訪問(wèn)服務(wù)端資源的問(wèn)題,https則完善了其安全問(wèn)題。因此在應(yīng)用層上,認(rèn)識(shí)這兩個(gè)協(xié)議非常有必要。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-434037.html
本章完~文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-434037.html
到了這里,關(guān)于【Linux網(wǎng)絡(luò)】網(wǎng)絡(luò)應(yīng)用層的 http 和 https協(xié)議的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!