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

通信安全之数据加密

        数据安全的需求如今越来越重要,本篇简单举例给日常的TCP/UDP通信加密,至少能让想干坏事的崽犯罪的成本更高一些(如果会一些BPF的,可能难不住这些崽),能让我们的数据更安全一点。

经典TCP socket编程

下面为大家常见的TCP socket编程示例:

客户端
/* client.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>  
#include <sys/types.h>   
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
//#include "myssl.h"int main(int argc, char *argv[])
{// 定义相关变量int sockfd;struct sockaddr_in serv_addr;char buf[1024] = {0};const char *greeting = "Hello from client";if(argc < 2){printf("please input the ip of the server..\n");return -1;}//获取并初始化服务端地址serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(8080);if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0){fprintf(stderr, "inet_pton failed[%d].\n", errno);return -1;}// 创建socketif((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){fprintf(stderr, "create socket failed[%d].\n", errno);return -1;}// 连接到服务器if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){fprintf(stderr, "connect failed[%d].\n", errno);return -1;}// 发送数据if(write(sockfd, greeting, strlen(greeting)) < 0){fprintf(stderr, "write failed[%d].\n", errno);return -1;}// 接收数据if(read(sockfd, buf, 1024) < 0){fprintf(stderr, "read failed[%d].\n", errno);return -1;}printf("received message:%s\n", buf);close(sockfd);
}
服务端
/* server.c */
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <arpa/inet.h>  
#include <sys/types.h>   
#include <sys/socket.h>  
#include <netinet/in.h>
#include <errno.h>
//#include "myssl.h"#define MAX_CNT 5int main(int argc, char *argv[])
{// 定义相关变量int server_fd, new_socket;int opt = 1; struct sockaddr_in serv_addr, cli_addr;socklen_t cli_addr_len;char buf[1024] = {0};const char *greeting = "Hello from server";// 创建socket文件描述符if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0){fprintf(stderr, "create socket failed[%d].\n", errno);return -1;}// 设置socket选项if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {  fprintf(stderr, "set socket failed[%d].\n", errno);return -1;  }// 绑定socket到指定端口和地址memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);serv_addr.sin_port = htons(8080);if(bind(server_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){fprintf(stderr, "create bind failed[%d].\n", errno);return -1;}// 监听if(listen(server_fd, MAX_CNT) < 0){fprintf(stderr, "listen failed[%d].\n", errno);return -1;}// 接受客户端连接请求memset(&cli_addr, 0, sizeof(cli_addr));cli_addr_len = sizeof(cli_addr);if((new_socket = accept(server_fd, (struct sockaddr *)&cli_addr, (socklen_t *)&cli_addr_len)) < 0 ){fprintf(stderr, "accept failed[%d].\n", errno);return -1;}printf("Client [%s-%d] connected.\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));// 接收数据if(read(new_socket, buf, 1024) < 0){fprintf(stderr, "read failed[%d].\n", errno);return -1;}printf("received message:%s\n", buf);// 发送数据if(write(new_socket, greeting, strlen(greeting)) < 0){fprintf(stderr, "write failed[%d].\n", errno);return -1;}// 关闭socketclose(new_socket);close(server_fd);printf("server closed.\n");return 0;
}

开启两个终端,运行结果如下:

数据加密方式TCP socket编程

封装加密初始化程序

        我们创建两个文件,一个为myssl.h,一个为对应的实现文件myssl.c,如下:

/* myssl.h */#ifndef __MYSSL_H_
#define __MYSSL_H_#include <openssl/ssl.h>typedef enum{SSL_MODE_SERVER,SSL_MODE_CLIENT
}SSL_MODE;//对象方法枚举SSL *init_ssl(char *cert_path, char *key_path, SSL_MODE mode, int fd);//初始化函数#endif
/* myssl.c */
#include <openssl/ssl.h>
#include <stdio.h>
#include <stdlib.h>
#include "myssl.h"SSL *init_ssl(char * cert_path, char * key_path, SSL_MODE mode, int fd)
{// 声明套件变量const SSL_METHOD *method;SSL_CTX *ctx;SSL *ssl = NULL;// 添加支持的算法,加载错误信息OpenSSL_add_all_algorithms();SSL_load_error_strings();// 获取对象方法// 不同版本的openssl对应的API也是有区别的,需要注意if(mode == SSL_MODE_SERVER){method = SSLv23_server_method();}else if(mode == SSL_MODE_CLIENT){method = SSLv23_client_method();}else{printf("unkown method\n");return NULL;}// 创建CTXctx = SSL_CTX_new(method);if(!ctx){printf("create SSL CTX failed.\n");return NULL;}// 读取证书(公钥)和密钥(私钥)if((SSL_CTX_use_certificate_file(ctx, cert_path, SSL_FILETYPE_PEM) <= 0)||(SSL_CTX_use_PrivateKey_file(ctx, key_path, SSL_FILETYPE_PEM) <= 0)){printf("not found file\n");return NULL;}// 创建SSLssl = SSL_new(ctx);if(!ssl){printf("failed create SSL.\n");return NULL;}// 绑定套接字的文件描述符到SSL中if(SSL_set_fd(ssl, fd) == 0){printf("SSL set fd failed.\n");return NULL;}// 连接套接字if((mode == SSL_MODE_SERVER && SSL_connect(ssl) <= 0)||(mode == SSL_MODE_CLIENT && SSL_connect(ssl) <= 0)){printf("failed handshake with ssl.\n");return NULL;}return ssl;
}

 修改经典socket编程代码

        我们来对上面的客户端和服务端程序做些修改,以期使得变成加密的套接字通信。

客户端
/* client.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>  
#include <sys/types.h>   
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include "myssl.h"int main(int argc, char *argv[])
{// 定义相关变量int sockfd;struct sockaddr_in serv_addr;char buf[1024] = {0};const char *greeting = "Hello from client";if(argc < 2){printf("please input the ip of the server..\n");return -1;}//获取并初始化服务端地址serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(8080);if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0){fprintf(stderr, "inet_pton failed[%d].\n", errno);return -1;}// 创建socketif((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){fprintf(stderr, "create socket failed[%d].\n", errno);return -1;}// 连接到服务器if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){fprintf(stderr, "connect failed[%d].\n", errno);return -1;}// 初始化加密函数SSL *ssl = init_ssl("./cert.pem", "./key.pem", SSL_MODE_CLIENT, sockfd);// 发送数据if(SSL_write(ssl, greeting, strlen(greeting)) < 0)	//if(write(sockfd, greeting, strlen(greeting)) < 0){fprintf(stderr, "write failed[%d].\n", errno);return -1;}// 接收数据if(SSL_read(ssl, buf, 1024) < 0) //if(read(sockfd, buf, 1024) < 0){fprintf(stderr, "read failed[%d].\n", errno);return -1;}printf("received message:%s\n", buf);close(sockfd);SSL_shutdown(ssl);SSL_free(ssl);
}
服务端
/* server.c */#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <arpa/inet.h>  
#include <sys/types.h>   
#include <sys/socket.h>  
#include <netinet/in.h>
#include <errno.h>
//#include "myssl.h"#define MAX_CNT 5int main(int argc, char *argv[])
{// 定义相关变量int server_fd, new_socket;int opt = 1;struct sockaddr_in serv_addr, cli_addr;socklen_t cli_addr_len;char buf[1024] = {0};const char *greeting = "Hello from server";// 创建socket文件描述符if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0){fprintf(stderr, "create socket failed[%d].\n", errno);return -1;}// 设置socket选项if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {  fprintf(stderr, "set socket failed[%d].\n", errno);return -1;  } // 绑定socket到指定端口和地址memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);serv_addr.sin_port = htons(8080);if(bind(server_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){fprintf(stderr, "create bind failed[%d].\n", errno);return -1;}// 监听if(listen(server_fd, MAX_CNT) < 0){fprintf(stderr, "listen failed[%d].\n", errno);return -1;}// 接受客户端连接请求memset(&cli_addr, 0, sizeof(cli_addr));cli_addr_len = sizeof(cli_addr);if((new_socket = accept(server_fd, (struct sockaddr *)&cli_addr, (socklen_t *)&cli_addr_len)) < 0 ){fprintf(stderr, "accept failed[%d].\n", errno);return -1;}		printf("Client [%s-%d] connected.\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));// 初始化加密函数SSL *ssl = init_ssl("./cert.pem", "./key.pem", SSL_MODE_SERVER, new_socket);// 接收数据if(SSL_read(ssl, buf, 1024) < 0) //if(read(new_socket, buf, 1024) < 0){fprintf(stderr, "read failed[%d].\n", errno);return -1;}printf("received message:%s\n", buf);// 发送数据if(SSL_write(ssl, greeting, strlen(greeting)) < 0) //if(write(new_socket, greeting, strlen(greeting)) < 0){fprintf(stderr, "write failed[%d].\n", errno);return -1;}// 关闭socketclose(new_socket);close(server_fd);SSL_shutdown(ssl);SSL_free(ssl);printf("server closed.\n");return 0;
}
Makefile

        为了方便总体编译,我们创建一个Makefile,内容如下:

LIBS=-lssl -lcrypto
all:gcc -o server server.c myssl.c $(LIBS)gcc -o client client.c myssl.c $(LIBS)
clean:rm -rf server client
证书、密钥

        为方便测试,我们利用openssl生成密钥key.pem及公钥文件cert.pem,命令如下:

密钥

$openssl genpkey -algorithm RSA -out key.pem

公钥(利用密钥生成,生成之前需要根据提示输入一些地址公司等信息)

$sudo openssl req -new -x509 -key key.pem -out cert.pem -days 3650

注意openssl的版本程序中用到的和命令行的这个要保持一致,结果如下:

编译问题

        在终端执行make命令,如果出现找不到<openssl/ssl.h>,那么你的系统环境可能没有安装openssl开发库,我们可以通过下面命令安装:

sudo apt-get update  
sudo apt-get install libssl-dev

安装完毕后,<openssl/ssl.h>应该可以在/usr/include/openssl/目录中找到。

如果安装成功之后还是报找不到头文件的错误,通过下面命令检查定位头文件所在位置:

dpkg -L libssl-dev | grep ssl.h

如果你确定环境中有这个头文件而其他方法都不行的话,可以试试手动添加路径指定,如下:

gcc -o myprogram myprogram.c -I/usr/include/openssl -lssl -lcrypto

如果方法都试遍了,我们只能尝试卸掉重新安装。

sudo apt-get remove --purge libssl-dev  
sudo apt-get update  
sudo apt-get install libssl-dev

如果报找不到openssl的某些API 或相关问题,此时则需参考下面的流程对源码做出修改。

补充

        因为openssl每个跨级的版本(0.9/1.0/3.0)API的变动较大(有些遗弃有些修改),兼容性不好,我们编写的应用源代码可能会需要做些修改(如果使用的openssl变动了版本)。如果没有openssl的源码,系统中只有库文件,我们可以通过objdump命令来检索其用的哪些API,方便我们替换修改,举例:

$objdump -Tt libxxx.so | grep SSL*

类似返回如下结果:

参考

B站爱吃甜食的老猫的视频

相关文章:

通信安全之数据加密

数据安全的需求如今越来越重要&#xff0c;本篇简单举例给日常的TCP/UDP通信加密&#xff0c;至少能让想干坏事的崽犯罪的成本更高一些&#xff08;如果会一些BPF的&#xff0c;可能难不住这些崽&#xff09;&#xff0c;能让我们的数据更安全一点。 经典TCP socket编程 下面…...

花一分钟简单认识 CSS 中的规则 —— 级联层 @layer

layer 简介&#xff1a; 声明级联层时&#xff0c;越靠后优先级越高。不属于任何级联层的样式&#xff0c;将自成一层匿名级联层&#xff0c;并置于所有层之后 —— 级别最高。 用法一&#xff1a;在同一文件中 layer base, special; layer special {/* 优先 */li { color: …...

K8s学习三(Pod与探针)

深入学习Pod Pod配置文件 写一个自己的配置文件,nginx-po.yaml apiVersion: v1 #api文档版本 kind: Pod #资源类型对象&#xff0c;也可以配置为像Development&#xff0c;StatefulSet这一类的对象 metadata: # Pod相关的元数据&#xff0c;用于描述Pod的数据name: nginx-po…...

leetcode - 678. Valid Parenthesis String

Description Given a string s containing only three types of characters: ‘(’, ‘)’ and ‘*’, return true if s is valid. The following rules define a valid string: Any left parenthesis ( must have a corresponding right parenthesis ). Any right parenth…...

索尼相机照片清理软件

在使用索尼相机拍摄照片的时候有时我们需要同时拍摄JPG格式和RAW格式&#xff0c;这在后期选图的时候给我们带来一些麻烦。我们固然可以选用Br来管理照片&#xff0c;但是现在我们可以有一个更轻量的软件&#xff08;8.8MB&#xff09;来做到一部分功能。 我们将照片从SD卡导出…...

比赛记录:Codeforces Global Round 25 A~E (猜猜题场)

传送门:CF [前题提要]:其实这场打的不是很好.A题一个sb错误看不出来,50min后才过,B题上来就Wa了一发,C题用了没必要的线段树,D题刚开始被60诈骗,一直在想按位考虑.幸好赛时猜出了E,然后又猜出来D,本来掉大分变成上大分…但是这场前几题大都是猜猜题,所以本来不想写题解的.但是…...

Windows系统安装OpenSSH结合VS Code远程ssh连接Ubuntu【内网穿透】

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-AwzyR2lkHKjD9HYl {font-family:"trebuchet ms",verdana,arial,sans-serif;f…...

Svg Flow Editor 原生svg流程图编辑器(五)

系列文章 Svg Flow Editor 原生svg流程图编辑器&#xff08;一&#xff09; Svg Flow Editor 原生svg流程图编辑器&#xff08;二&#xff09; Svg Flow Editor 原生svg流程图编辑器&#xff08;三&#xff09; Svg Flow Editor 原生svg流程图编辑器&#xff08;四&#xf…...

数字晶体管选型参数,结构原理,工艺与注意问题总结

🏡《总目录》 目录 1,概述2,工作原理2.1,AND 门(与门),2.2,OR 门(或门):2.3,NOT 门(非门):2.4,NAND 门(与非门):2.5,NOR 门(或非门):3,结构特点3.1,TTL(Transistor-Transistor Logic)晶体管...

lua学习笔记9(字典的学习)

print("********************字典的学习***********************") a{["凌少"]"傻逼",["我"]"天才",["age"]24,["daihao"]114514,["8848"]20000} --访问单个变量 print(a["凌少"])…...

第六篇: 3.5 性能效果 (Performance)- IAB/MRC及《增强现实广告效果测量指南1.0》

​​​​​​​ 翻译计划 第一篇概述—IAB与MRC及《增强现实广告效果测量指南》之目录、适用范围及术语第二篇 广告效果测量定义和其他矩阵之- 3.1 广告印象&#xff08;AD Impression&#xff09;第三篇 广告效果测量定义和其他矩阵之- 3.2 可见性 &#xff08;Viewability…...

mysql学习笔记NO.2

Java操作数据库、表笔记 1.创建数据库 创建数据库的步骤如下&#xff1a; 导入所需的Java数据库连接驱动&#xff08;如MySQL驱动&#xff09;。使用JDBC连接到数据库。执行SQL语句创建数据库。 import java.sql.Connection; import java.sql.DriverManager; import java.…...

C++11:lambda表达式 包装器

C11&#xff1a;lambda表达式 & 包装器 lambda表达式包装器functionbind lambda表达式 在C98中&#xff0c;如果想对一个结构体数组使用sort排序&#xff0c;那么我们就需要自己些仿函数。 比如以下结构体&#xff1a; struct Goods {string _name; // 名字double _pric…...

Node.js HTTP/2 CONTINUATION 拒绝服务漏洞(CVE-2024-27983)

Node.js 是开源、跨平台的 JavaScript 运行时环境。CONTINUATION泛洪攻击被发现存在于多个HTTP/2协议实现中。 在受影响版本中&#xff0c;由于Node.js针对HTTP/2协议的实现不当&#xff0c;未正确处理多个CONTINUATION帧的情况&#xff0c;在node::http2::Http2Session::~Htt…...

YOLOV8 + 双目测距

YOLOV8 双目测距 1. 环境配置2. 测距流程和原理2.1 测距流程2.2 测距原理 3. 代码部分解析3.1 相机参数stereoconfig.py3.2 测距部分3.3 主代码yolov8-stereo.py 4. 实验结果4.1 测距4.2 测距跟踪4.3 测距跟踪分割4.4 视频展示 相关文章 1. YOLOv5双目测距&#xff08;python&…...

前端:SVG绘制流程图

效果 代码 html代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>SVG流程图示例</title><style>/* CSS 样式 */</style><script src"js/index.js"></script…...

【Linux系列】如何确定当前运行的是 RHEL 9 还是 RHEL 8?

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

vscode开发java的插件和配置

推荐插件 .vscode/extensions.json {"recommendations": ["redhat.fabric8-analytics","ms-azuretools.vscode-docker","vscjava.vscode-java-pack","eamodio.gitlens","obkoro1.korofileheader","redhat.j…...

Mysql启动报错:本地计算机上的mysql服务启动后停止,某些服务在未由其他服务或程序使用时将自动停止

Mysql启动报错&#xff1a;本地计算机上的mysql服务启动后停止,某些服务在未由其他服务或程序使用时将自动停止 文章目录 Mysql启动报错&#xff1a;本地计算机上的mysql服务启动后停止,某些服务在未由其他服务或程序使用时将自动停止1. 备份mysql的data文件夹2. 重新构建 Wind…...

WPF程序添加托盘图标

程序添加托盘图标 UI层 //添加handycontrol的引用xmlns:hc"https://handyorg.github.io/handycontrol"//添加NotifyIcon图标 实现单击 双击 二级菜单点击功能<hc:NotifyIconText"通知"Token"Info"><hc:NotifyIcon.ContextMenu><…...

Python AOT编译卡在wasm-ld阶段?揭秘2026年新引入的WASI-SDK v22.0工具链冲突——附3行patch脚本+验证清单

第一章&#xff1a;Python AOT编译卡在wasm-ld阶段&#xff1f;揭秘2026年新引入的WASI-SDK v22.0工具链冲突——附3行patch脚本验证清单自2026年WASI-SDK v22.0发布以来&#xff0c;Python官方AOT编译流程&#xff08;基于pyodide-build aot&#xff09;在链接阶段频繁阻塞于w…...

Go Mutex 与 RWMutex 性能对比

在Go语言并发编程中&#xff0c;Mutex&#xff08;互斥锁&#xff09;和RWMutex&#xff08;读写锁&#xff09;是两种常用的同步机制。它们的性能差异直接影响高并发场景下的程序效率。本文将从多个角度对比两者的性能表现&#xff0c;帮助开发者根据实际需求选择合适的锁机制…...

隐私保护方案:OpenClaw+GLM-4.7-Flash本地化处理敏感数据

隐私保护方案&#xff1a;OpenClawGLM-4.7-Flash本地化处理敏感数据 1. 为什么需要本地化处理敏感数据&#xff1f; 去年我帮一位做财务咨询的朋友处理季度报表时&#xff0c;遇到了一个棘手问题。他需要分析上百份包含客户银行流水、身份证号等信息的Excel文件&#xff0c;但…...

英雄联盟智能辅助套件:重新定义MOBA游戏体验的开源工具集

英雄联盟智能辅助套件&#xff1a;重新定义MOBA游戏体验的开源工具集 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit League-Tool…...

MATLAB中扩展卡尔曼滤波与无迹卡尔曼滤波源代码:一键运行,误差对比及显示最大误差数字图像程...

MATLAB编写的EKF和UKF滤波程序源代码 扩展卡尔曼滤波、无迹卡尔曼滤波的MATLAB程序&#xff0c;有误差对比图像和最大误差数字的显示。 只有一个m文件&#xff0c;打开就能运行。 带中文注释。直接双击EKFUKFComparison.m就能看到两个滤波器在非线性系统里的较量。这个文件里塞…...

服务器频繁报soft lockup?手把手教你排查高负载进程与内核死锁问题

服务器频繁报soft lockup&#xff1f;手把手教你排查高负载进程与内核死锁问题 最近在运维工作中&#xff0c;你是否遇到过服务器突然弹出"kernel:NMI watchdog: BUG: soft lockup - CPU#X stuck for XXs!"这样的警告信息&#xff1f;这种内核软死锁问题看似不会立即…...

企业级React UI组件库实战指南:Element React深度解析与最佳实践

企业级React UI组件库实战指南&#xff1a;Element React深度解析与最佳实践 【免费下载链接】element-react Element UI 项目地址: https://gitcode.com/gh_mirrors/el/element-react Element React作为一款专业的企业级React UI组件库&#xff0c;为现代前端开发提供了…...

GLM-OCR在ComfyUI工作流中的应用:构建可视化OCR处理节点

GLM-OCR在ComfyUI工作流中的应用&#xff1a;构建可视化OCR处理节点 如果你经常用ComfyUI做图片生成或者编辑&#xff0c;可能会遇到一个挺麻烦的事儿&#xff1a;怎么把图片里的文字快速提取出来&#xff0c;然后用到下一步工作流里&#xff1f;比如&#xff0c;你想把一张海…...

效率直接起飞!盘点2026年全网顶尖的AI论文工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂的AI论文工具&#xff0c;实测提速效果惊人&#xff0c;覆盖选题构思、文献整理、内容生成、格式排版全流程&#xff0c;让你高效搞定论文&#xff0c;告别熬夜赶工。 一、全流程王者&#xff1a;一站式搞定论文全链路&…...

每日一道面试题 06|Spring Bean 的生命周期(高频必问)

面试题请完整说一下 Spring Bean 从加载到销毁的整个生命周期&#xff1f;有哪些关键扩展点&#xff1f;一、一句话概括生命周期Bean 从被 Spring 容器实例化 → 属性填充 → 初始化 → 正常使用 → 容器关闭时销毁的完整过程。二、标准生命周期流程&#xff08;按顺序背&#…...