当前位置: 首页 > news >正文

Linux网络http与https

应用层协议HTTP

提示
因为现在大多数都是https,所以就用https来介绍http,https比http多了一个加密功能,不影响介绍http。

什么是http

虽然我们说, 应用层协议是我们程序猿自己定的. 但实际上, 已经有大佬们定义了一些现成的, 又非常好用的应用层协议, 供我们直接参考使用. HTTP(超文本传输协议)就是其中之一。
在互联网世界中,HTTP(HyperText Transfer Protocol,超文本传输协议)是一个至关重要的协议。它定义了客户端(如浏览器)与服务器之间如何通信,以交换或传输超文本(如 HTML 文档)。
HTTP 协议是客户端与服务器之间通信的基础。客户端通过 HTTP 协议向服务器发送请求,服务器收到请求后处理并返回响应。HTTP 协议是一个无连接、无状态的协议,即每次请求都需要建立新的连接,且服务器不会保存客户端的状态信息。

域名

在这里插入图片描述

打开浏览器页面,我的默认搜索是百度。
红圈部分是网址,复制粘贴之后,我们无论打开哪个网页,在这个栏目当当中输入https://www.baidu.com/就可以跳转到百度搜索的首页。
这个网址是如何做到这种功能的呢?
网址——>域名——>域名解析——>IP地址

这是因为有域名解析这个功能,将网址转换成ip地址。
Windows打开命令窗口:
在这里插入图片描述
在这里插入图片描述
这里得到一个ip地址,我们输入到浏览器一下:
在这里插入图片描述
也就是说,每个域名都是ip地址,访问每个域名都是通过ip地址。

URL

在百度当中搜索
https://www.helloworld.net/p/4442555963
这一串我们简称为URL,也叫做:统一资源定位符。(网上所有的资源都可以用唯一的一个“字符串”标识获取)
在这里插入图片描述
网络行为
目前我们最常用的网络行为就是把别人的东西拿出来,把自己的东西传上去,我们访问的服务器可以理解为同时连接一台电脑,我们进入这台电脑获取数据或者是上传数据。
url就是搜索目录的存在。

urlencode 和 urldecode

像 / ? : 等这样的字符, 已经被 url 当做特殊意义理解了. 因此这些字符不能随意出现. 比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义。
搜索hello world
https://www.baidu.com/s?tn=15007414_15_dg&ie=utf-8&wd=hello%20world
搜索aaaa+??//: /&bbbb
https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&tn=15007414_15_dg&wd=aaaa%2B%3F%3F%2F%2F%3A%2F%26bbbb&oq=hello%2520world&rsv_pq=eb10b3d000010b64&rsv_t=aa46E6F5%2BL6oqrBlcwAIRYoHHt%2FkY40E5WdjW0FikHG%2B0Wo9hEJLKyWNfAMEq%2BhRJ5K2Pas&rqlang=cn&rsv_dl=tb&rsv_enter=1&rsv_sug3=18&rsv_sug1=15&rsv_sug7=100&rsv_sug2=0&rsv_btype=t&inputT=18981&rsv_sug4=18981

在这里插入图片描述

这里变成了这个样子,说明如果搜索的内容需要这些特殊字符,那么在输入的过程中就会进行转译。
(要求BS双方进行编码和解码)
转义的规则如下:

将需要转码的字符转为 16 进制,然后从右到左,取 4 位(不足 4 位直接处理),每 2 位
做一位,前面加上%,编码成%XY 格式

HTTP 常见 Header

Connection:keep-alive 保持长连接
Content-Type: 数据类型(text/html 等)
Content-Length: Body 的长度
Host: 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上;
User-Agent: 声明用户的操作系统和浏览器版本信息;
referer: 当前页面是从哪个页面跳转过来的;
Location: 搭配 3xx 状态码使用, 告诉客户端接下来要去哪里访问;
Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能;

http请求与响应

http从客户端发到服务器,是怎么发送和接收的呢?
是客户端请求,服务器响应。
请求的结构体:
在这里插入图片描述
这里的\r\n可以看作一种特殊字符,所有的请求内容都是连在一起的,只不过由\r\n隔离起来了而已。
在这里插入图片描述
这是请求的格式。
请求行:
Method是GET/POST,也就是获取与传输。(我们百分之95都是再用这两种命令)
在这里插入图片描述
假设要在网站中输入账号和密码,使用GET,就是通过URL提交的参数。(以问好作为分隔符,右侧是要提交的参数)
注意:参数数量受限,不私秘,会在URL当中体现。
如果用的是POST,那么参数会放在请求正文当中提交。

HTTP Version是http的版本。(1.0,1.1(用的多),2.0)
报头:
里面都是KV属性结构。(里面含有正文长度等等的属性,后面会详细说明)

那么报头的最后一行也是\r\n,怎么才能分辨报头与正文呢?
答案就是,在报头后面加上一个空行。
在这里插入图片描述

同理,请求就要有响应,响应也有自己的结构体:
在这里插入图片描述

Linux输入

telnet www.baidu.com 80
GET / HTTP/1.1
然后按两下回车(因为有空行)
在这里插入图片描述
这里就是报头,报头下面的其他东西就是网页了。
在这里插入图片描述
所以

首先说一下HTTP Version,请求客户端发送给服务器的时候,客户端是什么http版本,服务器就会响应什么http版本。

那么状态码是什么呢?
平时我们访问某个网页,突然蹦出来404,说帖子被删除或者是网页不见了,404就是状态码,后面说的话就是状态码描述符。(字符串版本的描述)

类别原因短语
1XXInformational(信息性状态码)接收的请求正在处理
2XXSuccess(成功状态码)请求正常处理完毕
3XXRedirection(重定向状态码)需要进行附加操作以完成请求
4XXClient Error(客户端错误状态码)服务器无法处理请求
5XXServer Error(服务器错误状态码)服务器处理请求出错

重定向:分为临时和永久。
临时:例如登录页面会跳转到微信或者是QQ,登录完毕之后就会跳转回去。
永久:例如某个域名不用了,公司创建了个新的域名,但是又需要照顾不知道新域名的老用户,所以就会在旧网站提示当前域名不再使用,将要跳转到新网站。(服务器给浏览器发报文,报头当中的Location会指导浏览器应该去访问新的网站)

(现在可以安装一个抓包软件来进行测试了,推荐Fiddler 或者 Postman)
抓包软件是如何工作的呢?
是客户端将http的请求发给Fiddler,Fiddler再发给服务器,相当于Fiddler是一个代理。

简单实现一个httpserver

预备知识

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
第一个参数是读取哪个套接字
第二个参数是读取到哪里
第三个参数是读取的长度
第四个参数是读取的方式

在这里插入图片描述

ssize_t send(int sockfd, const void *buf, size_t len, int flags);
第四个参数是写入方式

在这里插入图片描述
一个巨大的网页会包含非常多的元素,比如打开淘宝京东,琳琅满目的商品,标注的价格,推荐物品,图片,各种其他功能。——每一个元素都是资源,打开首页又很多图片,其实看到的每一张图片都是浏览器发送的访问请求,然后服务器给响应,通过渲染等等手段显示给浏览器。

一次请求响应一个资源,关闭连接——短连接。(http1.0)
客户端通过TCP与服务器建立链接,发送多个请求返回多个响应,在没有完成这些请求和响应之前不会关闭。——长连接(http1.1)

在网页当中插入图片,是需要知道ContentType。(http内容类型)

我们在访问B站的时候,会提示让我们去登录账号密码,登录之后,未来的几天再次进入B站就不用再去登录了,这是为什么呢?
首先明白一点,HTTP协议默认是无状态的,这意味着服务器不会主动记录或保留客户端(如浏览器)的请求历史信息。每个HTTP请求都是独立的,服务器处理完一个请求后,不会“记住”这个客户端的状态,下一次请求时服务器会将其视为全新的请求。
因为http对登录用户有会话保持功能。
原理version:(文件级)
在这里插入图片描述
这里就算是关闭浏览器再打开也可以进去,因为信息被保存在文件里。
在这里插入图片描述
在这里插入图片描述
Cookie是会自动消除的。

内存级如果关闭浏览器,再次打开B站就不会自动登录了。

可如果黑客窃取了cookie文件,就会造成巨大损失。(账号密码被盗,个人隐私泄露)
解决方案:
在这里插入图片描述
也就是说,就算黑客拿到了cookie也是ID,如果在自己的机器登录会被B站检测到,因为B站的session文件中有登录信息,如果IP不同就会让黑客登录账号与密码。(一定程度上避免了信息泄露)

代码实现

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><!-- <form action="/a/b/hello.html" method="post">name: <input type="text" name="name"><br>password: <input type="password" name="passwd"><br><input type="submit" value="提交"></form> --><h1>这个是我们的首页</h1><!-- <img src="/image/1.png" alt="这是一直猫" width="100" height="100"> 根据src向我们的服务器浏览器自动发起二次请求 --><!-- <img src="/image/2.jpg" alt="这是花"> -->
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><h1>这是第二张网页</h1><h1>这是第二张网页</h1><h1>这是第二张网页</h1><h1>这是第二张网页</h1><h1>这是第二张网页</h1><h1>这是第二张网页</h1><h1>这是第二张网页</h1><a href="http://120.78.126.148:8899">回到首页</a><a href="http://120.78.126.148:8899/x/y/world.html">到第三张网页</a>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><h1>这是第3张网页</h1><h1>这是第3张网页</h1><h1>这是第3张网页</h1><h1>这是第3张网页</h1><h1>这是第3张网页</h1><h1>这是第3张网页</h1><a href="http://120.78.126.148:8899">回到首页</a><a href="http://120.78.126.148:8899/a/b/hello.html">到第二张网页</a>
</body>
</html>
#pragma once#include <iostream>
#include <time.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>#define SIZE 1024#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4#define Screen 1
#define Onefile 2
#define Classfile 3#define LogFile "log.txt"class Log
{
public:Log(){printMethod = Screen;path = "./log/";}void Enable(int method){printMethod = method;}std::string levelToString(int level){switch (level){case Info:return "Info";case Debug:return "Debug";case Warning:return "Warning";case Error:return "Error";case Fatal:return "Fatal";default:return "None";}}void printLog(int level, const std::string &logtxt){switch (printMethod){case Screen:std::cout << logtxt << std::endl;break;case Onefile:printOneFile(LogFile, logtxt);break;case Classfile:printClassFile(level, logtxt);break;default:break;}}void printOneFile(const std::string &logname, const std::string &logtxt){std::string _logname = path + logname;int fd = open(_logname.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666); // "log.txt"if (fd < 0)return;write(fd, logtxt.c_str(), logtxt.size());close(fd);}void printClassFile(int level, const std::string &logtxt){std::string filename = LogFile;filename += ".";filename += levelToString(level); // "log.txt.Debug/Warning/Fatal"printOneFile(filename, logtxt);}~Log(){}void operator()(int level, const char *format, ...){time_t t = time(nullptr);struct tm *ctime = localtime(&t);char leftbuffer[SIZE];snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,ctime->tm_hour, ctime->tm_min, ctime->tm_sec);va_list s;va_start(s, format);char rightbuffer[SIZE];vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);va_end(s);// 格式:默认部分+自定义部分char logtxt[SIZE * 2];snprintf(logtxt, sizeof(logtxt), "%s %s", leftbuffer, rightbuffer);// printf("%s", logtxt); // 暂时打印printLog(level, logtxt);}private:int printMethod;std::string path;
};
Log lg;
#pragma once#include <iostream>
#include <memory>
#include <string>
#include <pthread.h>
#include <fstream>
#include <vector>
#include <sstream>
#include <sys/types.h>
#include <sys/socket.h>
#include <unordered_map>
#include "log.hpp"
#include "Socket.hpp"
using namespace std;
const string wwwroot="./wwwroot"; // web 根目录,在当前文件下的文件夹,里面存放的就是网页里的所有内容
const string sep = "\r\n";
const string homepage = "index.html";
static const int defaultport = 8080;
class HttpServer;
class ThreadData
{
public:ThreadData(int fd, HttpServer *s) : sockfd(fd), svr(s){}ThreadData(){}
public:int sockfd;HttpServer *svr;
};
class HttpRequest
{
public:void Deserialize(string req)//序列化{while(true){size_t pos = req.find(sep);if(pos == string::npos) break;string temp = req.substr(0, pos);if(temp.empty()) break;req_header.push_back(temp);req.erase(0, pos+sep.size());}text = req;}void Parse(){stringstream ss(req_header[0]);ss >> method >> url >> http_version;file_path = wwwroot; // ./wwwrootif(url == "/" || url == "/index.html")//条件满足判断为要访问首页{file_path += "/";file_path += homepage; // ./wwwroot/index.html}else file_path += url;// /a/b/c/d.html->./wwwroot/a/b/c/d.html,无论有多少个参数,都要从wwwroot的web根目录开始查询访问auto pos = file_path.rfind(".");if(pos == string::npos) suffix = ".html";//没找到后缀默认为是.htmlelse suffix = file_path.substr(pos);}void DebugPrint(){for(auto &line : req_header){cout << "--------------------------------" << endl;cout << line << "\n\n";}cout << "method: " << method << endl;cout << "url: " << url << endl;cout << "http_version: " << http_version << endl;cout << "file_path: " << file_path << endl;cout << text << endl;}
public:vector<string> req_header;//请求报头string text;//正文部分// 解析之后的结果string method;string url;string http_version;string file_path; // ./wwwroot/a/b/c.html 2.png文件类型string suffix;//文件后缀
};
class HttpServer
{
public:HttpServer(uint16_t port = defaultport):port_(port){content_type.insert({".html", "text/html"});content_type.insert({".png", "image/png"});}bool Start(){listensock_.Socket();listensock_.Bind(port_);listensock_.Listen();for (;;){string clientip;uint16_t clientport;int sockfd = listensock_.Accept(&clientip, &clientport);if (sockfd < 0)continue;lg(Info, "get a new connect, sockfd: %d", sockfd);pthread_t tid;ThreadData *td = new ThreadData(sockfd, this);pthread_create(&tid, nullptr, ThreadRun, td);}}static string ReadHtmlContent(const string &htmlpath)//http的本质就是读到固定格式的字符串进行分析在分拣中搜索资源,然后在响应回去{ifstream in(htmlpath, ios::binary);//要以二进制的方式去读,因为图片是按照二进制的方式存储的,不然图片会读取失败if(!in.is_open()) return "";in.seekg(0, ios_base::end);auto len = in.tellg();//文件大小in.seekg(0, ios_base::beg);string content;content.resize(len);in.read((char*)content.c_str(), content.size());in.close();return content;}string SuffixToDesc(const std::string &suffix){auto iter = content_type.find(suffix);if(iter == content_type.end()) return content_type[".html"];//没找到返回类型默认是.htmlelse return content_type[suffix];}void HandlerHttp(int sockfd){char buffer[10240];ssize_t n = recv(sockfd, buffer, sizeof(buffer) - 1, 0);if (n > 0){buffer[n] = 0;cout << buffer << endl; // 假设我们读取到的就是一个完整的,独立的http 请求//响应部分,网页的内容会被拼接到响应正文当中。//特定部分情况下,访问某个服务器URL就不会计算ip地址与端口号,所以剩下的部分就是RUL。//用户请求的时候,会在RUL当中包含请求的页面,什么样的资源,根据路径来寻找相应的资源HttpRequest req;req.Deserialize(buffer);req.Parse();//返回响应过程string text;bool ok = true;text = ReadHtmlContent(req.file_path); if(text.empty())//如果失败就返回404{ok = false;string err_html = wwwroot;err_html += "/";err_html += "err.html";text = ReadHtmlContent(err_html);}string response_line;if(ok)response_line = "HTTP/1.0 200 OK\r\n";elseresponse_line = "HTTP/1.0 404 Not Found\r\n";string response_header = "Content-Length: ";response_header += to_string(text.size()); // Content-Length: 11response_header += "\r\n";response_header += "Content-Type: ";//文件类型response_header += SuffixToDesc(req.suffix);response_header += "\r\n";response_header += "Set-Cookie: name=haha&&passwd=12345";//Cookie文件response_header += "\r\n";string blank_line = "\r\n"; // \nstring response = response_line;response += response_header;response += blank_line;response += text;send(sockfd, response.c_str(), response.size(), 0);}close(sockfd);}static void *ThreadRun(void *args){pthread_detach(pthread_self());ThreadData *td = static_cast<ThreadData *>(args);td->svr->HandlerHttp(td->sockfd);delete td;return nullptr;}~HttpServer(){}
private:Sock listensock_;uint16_t port_;unordered_map<string, string> content_type;//ContentType对照表
};
#include "HttpServer.hpp"int main(int argc, char *argv[])
{if(argc != 2){exit(1);}uint16_t port = std::stoi(argv[1]);std::unique_ptr<HttpServer> svr(new HttpServer(port));svr->Start();return 0;
}

HTTPS

什么是HTTPS

HTTP协议中,用户的信息要么在正文里,要么在URL里,很不安全。
HTTPS也是一个应用层协议. 是在 HTTP 协议的基础上引入了一个加密层. HTTP 协议内容都是按照文本的方式明文传输的. 这就导致在传输过程中出现一些被篡改的情况.
在这里插入图片描述
https = http+ssl
在应用层正文进行加密,然后通过协议栈发送给对方,对方也是在应用层进行解密读取到正文,除了双方的应用层,其他层是看不到这份报文的正文内容的。

加密

加密就是把 明文 (要传输的信息)进行一系列变换, 生成 密文 。
解密就是把 密文 再进行一系列变换, 还原成 明文 。
在这个加密和解密的过程中, 往往需要一个或者多个中间的数据, 辅助进行这个过程, 这样的数据称为 密钥。
例如:
要发送一个数字,7,然后我们可以先进行^5再发给对方,发过去的是2,对方 ^5之后就能拿到7了。
这里7就是明文,2就是密文,5就是密钥。

在以前,去浏览器下载某款应用,如果找不到官网的话,到了别的网站下载这个应用,会发生两种情况,一种是未被劫持,应用下载会成功;如果被劫持应用就会被中间的运营商给替换掉,换成别的应用。
由于我们通过网络传输的任何的数据包都会经过运营商的网络设备(路由器, 交换机等), 那么运营商的网络设备就可以解析出你传输的数据内容, 并进行篡改.
点击 “下载按钮”, 其实就是在给服务器发送了一个 HTTP 请求, 获取到的 HTTP 响应其实就包含了该 APP 的下载链接. 运营商劫持之后,会修改掉这个下载地址。
所以,因为 http 的内容是明文传输的,明文数据会经过路由器、wifi 热点、通信服务运营商、代理服务器等多个物理节点,如果信息在传输过程中被劫持,传输的内容就完全暴露了。劫持者还可以篡改传输的信息且不被双方察觉,这就是 中间人攻击 ,所以我们才需要对信息进行加密。

不止运营商可以劫持, 其他的 黑客 也可以用类似的手段进行劫持, 来窃取用户隐私信息, 或者篡改内容。
在互联网上, 明文传输是比较危险的事情!!!
HTTPS 就是在 HTTP 的基础上进行了加密, 进一步的来保证用户的信息安全。

常见的加密方式

对称加密
采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密,特征:加密和解密所用的密钥是相同的。
就像上面说的传输数字 7 的例子。
特点:算法公开、计算量⼩、加密速度快、加密效率⾼。

非对称加密
需要两个密钥来进行加密和解密,这两个密钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥)。
其中公开密钥可以让所有人都知道,私有密钥只能自己知道,私钥加密的内容可以被公钥进行解密,但是公钥加密的内容只能被私钥解密。
比如说我们发送给一个服务器一条信息(只有这个服务器有私钥),所有人通过公钥进行加密,其他人读取不了这些消息,只有服务器的私钥才能进行解密。
特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。
非对称加密要用到两个密钥, 一个叫做 “公钥”, 一个叫做 “私钥”. 公钥和私钥是配对的. 最大的缺点就是运算速度非常慢,比对称加密要慢很多.

数据摘要 && 数据指纹

数字指纹(数据摘要),其基本原理是利用单向散列函数(Hash 函数)对信息进行运算, 生成一串固定⻓度的数字摘要。数字指纹并不是一种加密机制,但可以用来判断数据有没有被篡改。(将一个字符串通过hash算法转化成一个固定长度,非常低概率冲突的固定长度字符串,被转化的这个字符串具有唯一性——MD5算法)
摘要特征:和加密算法的区别是,摘要严格意义不是加密,因为没有解密,只不过从摘要很难反推原信息,通常用来进行数据对比

上面说的这个例子:
在这里插入图片描述
在第一次输入账号密码认证的时候就会通过MD5算法形成数据摘要(因为每个人的账号是不相同的),然后返回给用户的浏览器,也就是cookit:ID。

百度网盘还有个秒传的功能,这个也是通过MD5的算法来实现的技术。
假设用户A上传了一部电影,电影形成了数据摘要存在了百度网盘的库里,过了一段时间用户B也要上传这部电影,在上传的时候,会将要上传的电影进行数据摘要,然后判断库里是否有这个电影,发现这部电影存在,就会将这个电影变成共享文件,让用户A和用户B通过软连接的方式连接到这个共享文件;如果用户B上传的不是这个电影,那么再进行上传即可。

数字签名
摘要也是可以进行加密的,加密的摘要就叫做数字签名。

HTTPS工作过程探究

逐步设计完善一套安全方案。
假设客户端给服务器发送数据,中间有黑客进行劫持。

方案一:只使用对称加密

在这里插入图片描述
引入对称加密之后, 即使数据被截获, 由于黑客不知道密钥是啥, 因此就无法进行解密, 也就不知道请求的真实内容是啥了,可真的是这样吗?
实则不然,因为密钥也是需要传输给服务器,服务器才知道密钥是什么,那么传输的途中密钥要不要加密呢?加密服务器又不知道了,不加密黑客也会截取到密钥,也能解开密文,所以这种方法不可靠。

方案二:只使用非对称加密

在这里插入图片描述
也就是说,这种方法可以暂时保证客户端传输给服务器的数据不被黑客劫持,但是服务器发送给客户端的数据会被劫持,因为黑客也有公钥,服务器用私钥加密过的密文会被解开。

方案三:双方都使用非对称加密

简单来讲,就是方案二中客户端也生成私钥和公钥,互相传送给对方公钥,双方通过自己的私钥加密,用对方的公钥进行解密。
这样看起来是安全的,但是有和方案二的客户端发送给服务器数据一样的漏洞,并且这种方法效率低下。

方案四:非对称加密+对称加密

在这里插入图片描述
这里本质就是服务器给客户端公钥,客户端通过公钥对自己形成的对称密钥进行加密传给服务器,因为只有服务器才有私钥进行解密,所以看起来就保证了C的安全性,以后的通信同C加密解密即可。
但是,方案二三四的那种漏洞是非常致命的,如果黑客从最开始就从中间进行操作了呢?

方案二三四的致命问题

在这里插入图片描述
如果中间人形成了自己的公钥私钥,将服务器向客户端发送的S替换成M,那么客户端加密C就是用中间人的M进行了加密,并且服务器和客户端都不知道,因为客户端加密之后被中间人拿到,中间人又将C+M进行解密得到C,再让C+S发送给服务器。
这种叫做MITM攻击。
所以说还需要进一步对方案四进行改造才可以解决这个问题。(问题的本质是客户端无法验证服务器发送给自己的公钥是否合法)

引入证书

在边境,有关人员如何确定入境与出境人的身份合法?那就是身份证护照等等“证书”,并且是权威机构颁发的(当地政府)。
同理:服务端在使用 HTTPS 前,需要向 CA 机构申领一份数字证书,数字证书里含有证书申请者信息、公钥信息等。服务器把证书传输给浏览器,浏览器从证书里获取公钥就行了,证书就如身份证,证明服务端公钥的权威性

证书的原理
在这里插入图片描述
1.申请认证证书,首先服务器要有自己的公钥和密钥。准备好:域名/法人/服务器自己的公钥,生成.csr文件发给CA机构去申请证书。
2.CA机构审核是否合法。
3.CA机构审核合法之后进行签发证书,这个证书不是纸笔打印的那种证书,而是安装到服务器上的。
4.服务器发送给客户端证书,不单单是公钥这么简单了。(证书里面有服务器的公钥,这就防止了中间人篡改公钥)
5.客户端验证服务器的证书是否合法。
6.合法之后在进行密钥协商。(发送对称密钥)

CSR文件生成
在这里插入图片描述
服务器对应的公司会将自己的信息生成csr文件,然后生成一个公钥和私钥,这个私钥服务器要自己保存。(这里的公钥是面向客户端的,发送给了CA机构进行认证,私钥就是服务器自己的私钥,也就是说在形成CSR文件前服务器没有公钥和私钥)
签名
在这里插入图片描述

这是CA签名的过程,数据就是证书当中的明文:
在这里插入图片描述
将这个明文进行数据摘要形成一段数据,然后用CA机构自己的私钥进行加密就形成了签名。
然后再次拿出将明文和这个签名合二为一就形成了带有签名的证书。
在这里插入图片描述
注意:签名的形成是基于非对称加密算法。
CA机构也有自己的公钥与私钥。
为什么签名不直接加密,而是要先 hash 形成摘要?
缩⼩签名密文的⻓度,加快数字签名的验证签名的运算速度。

方案五:非对称加密 + 对称加密 + 证书认证

在这里插入图片描述
客户端认证的时候,要拆开签名与明文,进行对比。
当然,每个客户端在出厂的时候都会内置很多权威机构CA的公钥。(和服务器的公钥无关)
在形成签名的时候,CA机构用自己的私钥进行加密,此刻进行认证就需要用CA机构的公钥进行解密形成散列值——数据摘要。
然后让明文也进行数据摘要。
在这里插入图片描述
客户端只认CA的公钥,也就是说,签名只有CA机构才有资格形成签名。(中间人没有CA的私钥,无法修改签名)
这样就不怕黑客修改明文了,就算改了签名,客户端也没有黑客的公钥,无法对签名进行解密,上面的散列值等式就不成立。

可如果黑客将整个证书全都掉包了呢?(黑客自己进行CA认证,发送给客户端)那就搞笑了,浏览器申请访问的是A网站,返回来的证书是B网站的,域名不同,也会被识别出来。

这样就可以防止中间人从一开始进行替换服务器公钥的操作了。

总结HTTPS的保密三组

HTTPS 工作过程中涉及到的密钥有三组.
第一组(非对称加密): 用于校验证书是否被篡改. 服务器持有私钥(私钥在形成 CSR 文件与申请证书时获得), 客户端持有公钥(操作系统包含了可信任的 CA 认证机构有哪些, 同时持有对应的公钥). 服务器在客户端请求时,返回携带签名的证书. 客户端通过这个公钥进行证书验证, 保证证书的合法性,进一步保证证书中携带的服务端公钥权威性。
第⼆组(非对称加密): 用于协商生成对称加密的密钥. 客户端用收到的 CA 证书中的公钥(是可被信任的)给随机生成的对称加密的密钥加密, 传输给服务器, 服务器通过私钥解密获取到对称加密密钥.
第三组(对称加密): 客户端和服务器后续传输的数据都通过这个对称密钥加密解密. 其实一切的关键都是围绕这个对称加密的密钥. 其他的机制都是辅助这个密钥工作的.

相关文章:

Linux网络http与https

应用层协议HTTP 提示 因为现在大多数都是https&#xff0c;所以就用https来介绍http&#xff0c;https比http多了一个加密功能&#xff0c;不影响介绍http。 什么是http 虽然我们说, 应用层协议是我们程序猿自己定的. 但实际上, 已经有大佬们定义了一些现成的, 又非常好用的…...

C++ 算法(2):STL list 完全解析,从入门到高效使用

1. list概述 std::list是C标准模板库(STL)中的一个双向链表容器。与vector和deque不同&#xff0c;list不支持随机访问&#xff0c;但它在任何位置插入和删除元素都非常高效&#xff0c;时间复杂度为O(1)。 2. list的基本特性 双向链表结构&#xff1a;每个元素都包含指向前驱…...

【Linux实践系列】:匿名管道收尾+完善shell外壳程序

&#x1f525; 本文专栏&#xff1a;Linux Linux实践项目 &#x1f338;作者主页&#xff1a;努力努力再努力wz &#x1f4aa; 今日博客励志语录&#xff1a; 人生总会有自己能力所不及的范围&#xff0c;但是如果你在你能力所及的范围尽了全部的努力&#xff0c;那你还有什么遗…...

Linux基本指令2

1.head 查看文件的前面内容 head 路径 &#xff1a;查看路径开头部分内容&#xff0c;如下图&#xff1a;head /var/log/messages查看/var/log/messages这个日志中前面内容 head -数字 路径 &#xff1a;查看路径开头指定数字行部分内容&#xff0c;如下图&#xff1a;he…...

Tkinter使用Canvas绘制图形

在Tkinter中,Canvas是一个非常强大的控件,用于绘制图形、显示图片和实现自定义图形界面。通过Canvas,您可以绘制各种形状、线条、文本等,并且能够进行灵活的动画和交互。掌握Canvas的使用将使您能够创建丰富的图形界面。 8.1 创建Canvas控件 Canvas控件是一个区域,用于绘…...

CF985G Team Players

我敢赌&#xff0c;就算你知道怎么做&#xff0c;也必然得调试半天才能 AC。 [Problem Discription] \color{blue}{\texttt{[Problem Discription]}} [Problem Discription] 图片来自洛谷。 [Analysis] \color{blue}{\texttt{[Analysis]}} [Analysis] 显然不可能正面计算。所以…...

ngx_conf_read_token - events

file_size ngx_file_size(&cf->conf_file->file.info); 获取 配置文件的大小 此时 file_size364 for ( ;; ) {if (b->pos > b->last) { 此时 b->pos 0x5cd4701487e4 b->last 0x5cd47014893c b->start0x5cd4701487d0 条件不成立 ch *b->pos;…...

L2范数与权重衰退

权重衰退 定义损失函数 $ \ell(\mathbf{w}, b) $ 来衡量模型的预测值与真实值的差距 使用L2范数作为硬性限制 通过限制参数值的选择范围来控制模型容量 min ⁡ ℓ ( w , b ) s u b j e c t t o ∥ w ∥ 2 ≤ θ \min \ell(\mathbf{w}, b) \quad \\ subject \ to \|\mathbf{w…...

计算机组成原理笔记(十四)——3.4指令类型

一台计算机的指令系统可以有上百条指令&#xff0c;这些指令按其功能可以分成几种类型&#xff0c;下面分别介绍。 3.4.1数据传送类指令 一、核心概念与功能定位 数据传送类指令是计算机指令系统中最基础的指令类型&#xff0c;负责在 寄存器、主存、I/O设备 之间高效复制数…...

GM DC Monitor v2.0 数据中心监控预警平台-CMDB使用教程(第九篇)

SNMP配置管理功能使用手册 本模块主要用于导入设备厂家的mib库文件&#xff0c;也可以手工创建对应的oid信息&#xff0c;用以实现设备的被动监控功能。 另&#xff1a;系统部署完毕后&#xff0c;已经集成了个别厂家的MIB库数据。 设计思路及使用教程 设计思路&#xff1a;通…...

try-with-resources 详解

try-with-resources 详解 一、基本概念 try-with-resources 是 Java 7 引入的语法结构&#xff0c;用于自动管理资源&#xff08;如文件流、数据库连接等需要关闭的对象&#xff09;。 核心特点 自动资源释放&#xff1a;无需手动调用 close() 简洁代码&#xff1a;减少 tr…...

第二十四:查看当前 端口号是否被占用

查看当前 端口号是否被占用&#xff1a; mac 情况下&#xff1a; lsof -i :端口号 netstat -an | grep 端口号 系统将显示监听该端口的进程信息&#xff0c;包括进程名称、进程ID、用户和协议等。如果需要更多信息&#xff0c;可以添加-P和-n参数&#xff0c;例如&#xf…...

【数据结构与算法】——堆(补充)

前言 上一篇文章讲解了堆的概念和堆排序&#xff0c;本文是对堆的内容补充 主要包括&#xff1a;堆排序的时间复杂度、TOP 这里写目录标题 前言正文堆排序的时间复杂度TOP-K 正文 堆排序的时间复杂度 前文提到&#xff0c;利用堆的思想完成的堆排序的代码如下&#xff08;包…...

【Web功能测试】Web商城搜索模块测试用例设计深度解析

Web商城的搜索模块功能测试用例设计 1.搜索功能设计 1.1 搜索框设计 位置显眼&#xff1a;通常置于页面顶部中央&#xff0c;符合用户习惯。 智能提示&#xff08;Autocomplete&#xff09;&#xff1a;输入时实时推荐关键词、商品或分类&#xff08;如“手机 苹果”&#x…...

ubuntu 18.04安装tomcat,zookeeper,kafka,hadoop,MySQL,maxwell

事情是这样的&#xff0c;因为昨天发现我用的ubuntu16.04官方不维护了&#xff0c;以及之前就觉得不是很好用&#xff0c;于是升级到了18.04。如图&#xff1a; 但是&#xff01;由于为备份升级前忘记关闭服务&#xff0c;上面装好的东西所剩无几。 于是我重装了。。。 如何启…...

设计模式(结构型)-享元模式

摘要 在软件开发的广阔领域中&#xff0c;随着系统规模的不断膨胀&#xff0c;资源的有效利用逐渐成为了一个至关重要的议题。当一个系统中存在大量相似的对象时&#xff0c;如何优化这些对象的管理&#xff0c;减少内存的占用&#xff0c;提升系统的整体性能&#xff0c;成为了…...

1.1显存

显存是显卡&#xff08;GPU&#xff09;专用的高性能内存&#xff0c;负责存储渲染所需的纹理、帧缓冲、几何数据等。其设计直接影响图形性能、分辨率和复杂场景处理能力 苹果统一内存&#xff08;Unified Memory&#xff09;、集成显卡共享内存&#xff08;Integrated Graphi…...

C# 选择文件的路径、导出文件储存路径

1、选择导入文件&#xff0c;获取其路径 C#通过这段代码将弹出一个文件选择对话框&#xff0c;允许用户选择一个文件&#xff0c;并返回所选文件的完整路径。如果用户取消了选择&#xff0c;则直接返回结束函数。 string OpenFilePath;//存储选择到的文件的完整路径OpenFileDia…...

【最后203篇系列】027 基于消息队列的处理架构

起因 之所以写这篇文章&#xff0c;主要是梳理一下进展。因为同时研究好几块内容&#xff0c;切换起来要点时间。这次也是因为协作的同事们把各自的分工都搞定了&#xff0c;瓶颈反而在我自己这里&#xff0c;哈哈。 除了帮自己思路恢复过来&#xff0c;我觉得这方法可能也有…...

多线程与Tkinter界面交互

在现代图形用户界面(GUI)应用程序中,可能会遇到需要长时间运行的任务,例如网络请求、数据处理或文件读取等。如果这些任务直接在主线程中运行,会导致GUI界面“卡顿”或“不响应”。为了保持界面流畅和响应用户操作,我们可以通过使用多线程来将这些任务移到后台运行。然而…...

【工程开发】LLMC准确高效的LLM压缩工具(一)

​【文献阅读】LLMC: Benchmarking Large Language Model Quantization with a Versatile Compression Toolkit 北航 2024年10月 摘要 大语言模型&#xff08;LLMs&#xff09;的最新进展凭借其卓越的涌现能力和推理能力&#xff0c;正推动我们迈向通用人工智能。然而&#…...

回顾CSA,CSA复习

RHCSA redhat certificate system Administrator RHCE redhat certificate engineer 回顾CSA 文件管理 创建文件&#xff1a;touch 、重定向、vim 阅读文件&#xff1a;cat看短小的文件、vim、head看文件前面部分、tail看文件的尾部内容、more、less看文档使用more和less…...

基于电子等排体的3D分子生成模型 ShEPhERD - 评测

一、背景介绍 ShEPhERD 是一个由 MIT 开发的一个 3D 相互作用感知的 ligand-based的分子生成模型&#xff0c;以 arXiv 预印本的形式发表于 2024 年&#xff0c;被ICLR2025 会议接收。文章链接&#xff1a;https://openreview.net/pdf?idKSLkFYHlYg ShEPhERD 是一种基于去噪扩…...

平凡日子里的挣扎

2025年4月13日&#xff0c;9~23℃&#xff0c;好 待办&#xff1a; 融智云考平台《物理》《物理2》~~《地理》《地理1》~~重修试卷 卫健委统考监考&#xff08;2025年4月12日早上7点半&#xff09; 冶金《物理》课程标准 冶金《物理》教案 期中教学检查——自查表材料&#xff…...

智能制造方案精读:117页MES制造执行系统解决方案【附全文阅读】

本方案围绕制造执行系统(MES)展开,阐述了智能制造相关概念及发展趋势,指出 MES 是连接 ERP 与生产现场的关键系统。介绍其在加工、装配及其他场景的应用,通过实例展示各场景下的功能、特点和实施效果,如实现生产信息可视化、产品追溯、设备监控等。还提及实施 MES 面临的…...

[推荐]AI驱动的知识图谱生成器(AI Powered Knowledge Graph Generator)

网址&#xff1a;https://github.com/robert-mcdermott/ai-knowledge-graph# 一、介绍 简介&#xff1a;以非结构化文本文档为输入&#xff0c;使用您选择的LLM以主语-谓语-宾语 (SPO) 三元组的形式提取知识&#xff0c;并将这些关系可视化为交互式知识图谱 特点&#xff1a…...

波束形成(BF)从算法仿真到工程源码实现-第七节-关于波束10个基本概念

一、波束10个基本概念 1.作用&#xff1a; 对多路麦克风信号进行合并处理&#xff0c;抑制非目标方向的干扰信号&#xff0c;增强目标方向的声音信号。 2.原理&#xff1a; 调整相位阵列的基本单元参数&#xff0c;使得某些角度的信号获得相长干涉&#xff0c;而另一些角度的…...

深度学习(第一集)

123 import torch# 创建一个需要计算梯度的张量 x1 torch.tensor([2.0], requires_gradTrue)# 定义一个简单的函数 y x^2 y x1 ** 4# 计算梯度 y.backward()print("x1.grad 的值&#xff1a;", ) # 打印 x1.grad print("x1.grad 的值&#xff1a;", x1…...

Spring 事务传播行为

在Spring框架中,事务传播行为(Transaction Propagation)定义了事务在多个方法调用之间的行为方式。理解这些传播行为对于设计可靠的事务管理策略至关重要。以下是Spring支持的七种事务传播行为及其应用场景的详细说明: 1. REQUIRED(默认) 行为:如果当前存在事务,则加入…...

搬运机器人的基本工作场景及原理

搬运机器人广泛应用于工业生产中&#xff0c;主要用于搬运、堆放、装配等工作。它通过机械手臂的运动&#xff0c;结合机器视觉技术完成各种自动化作业。 一、搬运机器人的设计原理 搬运机器人通常采用可移动门架式结构&#xff0c;手臂承载机构安装在导轨上&#xff0c;可以沿…...

Ubuntu终端中常用的快捷键整理

1. 导航与编辑 光标移动&#xff1a; Ctrl A&#xff1a;跳转到行首。 Ctrl E&#xff1a;跳转到行尾。 Alt B&#xff1a;向左移动一个单词&#xff08;或 Ctrl ←&#xff09;。 Alt F&#xff1a;向右移动一个单词&#xff08;或 Ctrl →&#xff09;。 删除操作…...

mysql安装-MySQL MGR(Group Replication)+ ProxySQL 架构

文章目录 前言一、环境规划二、安装 MySQL 8.0.36&#xff08;主库&#xff0c;CentOS 9&#xff09;2.1 添加 Yum 源2.2 安装 MySQL 8.0.362.3 初始化 三、配置主库 my.cnf&#xff08;192.168.1.101&#xff09;四、&#xff08;可选&#xff09;创建远程可访问的用户&#x…...

Opencv使用cuda实现图像处理

main.py import os import cv2 print(fOpenCV: {cv2.__version__} for python installed and working) image cv2.imread(bus.jpg) if image is None:print("无法加载图像1") print(cv2.cuda.getCudaEnabledDeviceCount()) cv2.cuda.setDevice(0) cv2.cuda.printCu…...

ubuntu 安装samba

ubuntu 版本&#xff1a;Ubuntu 24.04.2 LTS 1. 保证连网 2. 安装samba sudo apt install samba 在安装结束以后&#xff0c;我们可以使用下面的命令来查看安装&#xff1a; apt list | grep samba freeipa-client-samba/noble 4.11.1-2 amd64 ldb-tools/noble 2:2.8.0samba…...

山东大学软件学院创新项目实训开发日志(12)之将对话记录保存到数据库中

在之前的功能开发中&#xff0c;已经成功将deepseekAPI接口接入到springbootvue项目中&#xff0c;所以下一步的操作是将对话和消息记录保存到数据库中 在之前的开发日志中提到数据库建表&#xff0c;所以在此刻需要用到两个表&#xff0c;conversation表和message表&#xff…...

欢乐力扣:反转链表二

文章目录 1、题目描述2、思路 1、题目描述 反转链表二。  给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 2、思路 参考官方题解&#xff0c;基本思路…...

【CS*N是狗】亲测可用!!WIN11上禁用Chrome自动更新IDM插件

现象&#xff1a;每次打开chrome后IDM会弹出提示插件版本不一致。经过排查后发现是chrome把IDM插件给更新了&#xff0c;导致IDM提示版本不匹配。经过摸索后&#xff0c;得到了可行的方案。 第一步&#xff0c;打开Chrome&#xff0c;把IDM插件卸载掉&#xff0c;然后重新安装I…...

Linux:DNS服务配置(课堂实验总结)

遇到的问题&#xff0c;都有解决方案&#xff0c;希望我的博客能为你提供一点帮助。 操作系统&#xff1a;rocky Linux 9.5 ​​一、配置DNS服务器的核心步骤​​ 步骤 1&#xff1a;安装 BIND 软件​​ ​​检查是否安装​​&#xff1a; rpm -qa | grep "^bind"…...

啥是Spring,有什么用,既然收费,如何免费创建SpringBoot项目,依赖下载不下来的解决方法,解决99%问题!

一、啥是Spring&#xff0c;为啥选择它 我们平常说的Spring指的是Spring全家桶&#xff0c;我们为什么要选择Spring&#xff0c;看看官方的话&#xff1a; 意思就是&#xff1a;用这个东西&#xff0c;又快又好又安全&#xff0c;反正就是好处全占了&#xff0c;所以我们选择它…...

【LeetCode】算法详解#4 ---合并区间

1.题目介绍 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 1 < intervals.length < 104interval…...

安装树莓派3B+环境

目录 一、安装树莓派3B环境 1.1 格式化SD卡 1.2 环境安装与配置 1.2.1 安装Raspberry Pi 1.2.2 SSH访问树莓派 1.3 创建用户账号 二、在树莓派上用C和Python编程运行一个简单的程序 2.1 C语言程序 2.2 Python程序 三、总结 树莓派是一款功能强大的微型计算机&#xf…...

​​STM32(3.3V 系统)通过串口直接向 ATmega328P(5V 系统)发送数据​​,居然能正常通信

​​核心结论​​ 如果 ​​STM32&#xff08;3.3V 系统&#xff09;通过串口直接向 ATmega328P&#xff08;5V 系统&#xff09;发送数据​​&#xff0c;​​3.3V 的 TX 高电平可能无法被 ATmega328P 可靠识别为逻辑“1”​​&#xff01;以下是详细分析&#xff1a; ​​1.…...

Java 8中的Lambda 和 Stream (from Effective Java 第三版)

42.Lambda 优先于匿名类 在之前的做法中&#xff08;Historically&#xff09;&#xff0c;使用单个抽象方法的接口&#xff08;或很少的抽象类【只有一个抽象方法的抽象类数量比较少】&#xff09;被用作函数类型。它们的实例称为函数对象&#xff0c;代表一个函数或一种行为。…...

MIPI协议介绍

MIPI协议介绍 mipi 协议分为 CSI 和DSI,两者的区别在于 CSI用于接收sensor数据流 DSI用于连接显示屏 csi分类 csi 分为 csi2 和 csi3 csi2根据物理层分为 c-phy 和 d-phy, csi-3采用的是m-phy 一般采用csi2 c-phy 和 d-phy的区别 d-phy的时钟线和数据线是分开的,2根线一对…...

深入解析 HTML 中 `<script>` 标签的 async 和 defer 属性

一、背景与问题 在网页性能优化中&#xff0c;脚本的加载和执行方式直接影响页面渲染速度和用户体验。传统 <script> 标签的阻塞行为可能导致页面“白屏”&#xff0c;而 async 和 defer 属性提供了非阻塞的解决方案。本周重点研究二者的差异、适用场景及实际应用。 二、…...

【从0到1学Elasticsearch】Elasticsearch从入门到精通(上)

黑马商城作为一个电商项目&#xff0c;商品的搜索肯定是访问频率最高的页面之一。目前搜索功能是基于数据库的模糊搜索来实现的&#xff0c;存在很多问题。 首先&#xff0c;查询效率较低。 由于数据库模糊查询不走索引&#xff0c;在数据量较大的时候&#xff0c;查询性能很差…...

2.0 全栈运维管理:Linux网络基础核心概念解析、Proxmox网络组件详解、虚拟化网络模型分类

本文是Proxmox VE 全栈管理体系的系列文章之一&#xff0c;如果对 Proxmox VE 全栈管理感兴趣&#xff0c;可以关注“Proxmox VE 全栈管理”专栏&#xff0c;后续文章将围绕该体系&#xff0c;从多个维度深入展开。 摘要&#xff1a;Linux 网络基础借助桥接、VLAN 和 Bonding 实…...

案例驱动的 IT 团队管理:创新与突破之路: 第四章 危机应对:从风险预见到创新破局-4.1.3重构过程中的团队士气管理

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 案例驱动的 IT 团队管理&#xff1a;创新与突破之路 - 第四章 危机应对&#xff1a;从风险预见到创新破局4.1.3 重构过程中的团队士气管理1. 技术债务重构与团队士气的矛盾2…...

洛谷刷题小结

#include <iostream> using namespace std; int n, m,ans0; char s[105][105]; //深搜 void dfs(int x, int y) {//将搜索到的水坑看为干地s[x][y] .;//确定八个方向int next[8][2] {{0,1},{0,-1},{1,0},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1},};//朝八个方向搜索for (in…...

Android Compose 权限申请完整指南

Android Compose 权限申请完整指南 在 Jetpack Compose 中处理运行时权限申请需要结合传统的权限 API 和 Compose 的状态管理。以下是完整的实现方案&#xff1a; 1. 基本权限申请流程 添加依赖 implementation "com.google.accompanist:accompanist-permissions:0.34…...