20242817李臻-安全文件传输系统-项目验收

安全文件传输系统项目报告

项目概述

本实验旨在设计并实现一个完整的安全文件管理系统,基于SM2+SM3+SM4混合密码体系,构建了一个具备高安全性的C/S架构文件传输平台。项目采用C/S架构,使用Qt框架开发,满足Linux系统调用、Socket网络编程、多线程处理等技术要求。

开发环境

  • 处理器:x86_64架构处理器
  • 操作系统:Ubuntu 20.04
  • 开发框架:Qt5
  • 数据库:SQLite 3
  • 密码库:gmssl

Gitee地址:

https://gitee.com/li-zhen1215/homework/tree/master/Secure%20File%20Transfer%20System

一、 功能完成以及完善情况

系统流程图
在这里插入图片描述

用户登录

系统采用登录验证机制作为入口。用户启动客户端后,首先进入登录界面:

  • 账号验证:
    • 若用户尚未注册账号,系统将引导其完成注册流程,创建合法用户信息;
    • 若用户已有账号,则可直接输入凭证完成身份验证。

进入主界面

登录成功后,用户将进入系统主界面,该界面集成了全部核心功能模块,。

文件管理功能

主界面提供了一系列文件传输和管理功能,具体包括:

  • 文件上传:用户可将本地文件上传至服务器;
  • 文件下载:可从服务器下载所需文件到本地;
  • 文件删除:允许用户删除自己上传的文件;
  • 刷新列表:实时刷新当前文件列表,查看最新文件信息;
  • 下载日志:支持用户查看文件下载历史记录,实现基本的审计追踪。

注销与退出

用户完成所需操作后,可选择注销账号,安全退出系统,确保账号信息和数据传输的安全性。

系统特点

  • 支持多用户并发访问:通过多线程/多连接机制,系统可同时处理多个用户请求;
  • 审计功能完善:系统记录用户操作日志,有助于行为追踪和系统安全审查。

1、总体架构完成情况

C/S架构实现

  • 服务器端: ServerCore类继承QTcpServer,实现多线程并发处理
  • 客户端: Qt GUI应用程序,提供用户友好的图形界面
  • 网络通信: 基于TCP Socket的可靠数据传输

系统架构图

在这里插入图片描述


2 、核心模块架构

2.1 客户端架构

Client/
├── MainWindow              // 主界面管理
├── LoginWindow            // 登录界面
├── RegisterWindow         // 注册界面
├── FileTransfer           // 文件传输核心
├── SecurityManager        // 密码学操作
└── AuditLogger           // 审计日志

2.2 服务器架构

Server/
├── ServerCore             // 服务器核心 (继承QTcpServer)
├── ClientHandler          // 客户端连接处理
├── Database               // 数据库操作
├── SecurityManager        // 服务器密码学管理
└── AuditLogger           // 服务器审计系统

3、功能完成以及完善情况

3.1 用户管理系统

当用户首次使用系统时,需要进行注册。用户名和口令是进入系统的凭证,用户名用作实现访问控制功能,而口令作为验证用户身份的唯一凭证,只有口令和用户名相对应,用户才能正确进入系统。

3.1.1 用户注册功能

实现思路

  • 用户输入用户名和密码
  • 客户端发送注册请求到服务器
  • 服务器进行SM3密码哈希处理
  • 存储到SQLite数据库

为确保身份鉴别的安全性,口令仅保存经过 SM3 哈希算法计算后的哈希值,并采用加盐机制以增强抗攻击能力。
核心实现代码

// 密码哈希处理 - SecurityManager类
QByteArray SecurityManager::hashPasswordWithSalt(const QString& password, const QByteArray& salt) {QByteArray actualSalt = salt.isEmpty() ? generateSalt() : salt;QByteArray combined = password.toUtf8() + actualSalt;// 10000轮SM3哈希运算 (PBKDF2-SM3)QByteArray hash = combined;const int rounds = 10000;for (int i = 0; i < rounds; i++) {SM3_CTX ctx;sm3_init(&ctx);sm3_update(&ctx, (const uint8_t*)hash.constData(), hash.size());uint8_t dgst[32];sm3_finish(&ctx, dgst);hash = QByteArray((char*)dgst, 32);}return actualSalt + hash; // [盐值32字节][哈希32字节]
}

注册用户界面
在这里插入图片描述
服务器端注册日志输出
在这里插入图片描述

3.1.2 用户登录认证

注册成功后,用户可以进入程序主界面,对自己的文件进行管理。

实现思路

  • 用户输入凭据后,客户端与服务器进行SM2密钥协商
  • 建立安全信道后发送登录请求
  • 服务器验证密码哈希
  • 建立用户会话

核心实现代码

// SM2密钥协商 - 客户端
bool SecurityManager::performClientHandshake(QTcpSocket* socket) {// 1. 接收服务器SM2公钥QByteArray serverPublicKeyBytes = readData(socket, 64);// 2. 生成会话密钥sessionKey = generateRandomKey(16);// 3. SM2加密会话密钥QByteArray encryptedSessionKey = encryptWithSM2PublicKey(sessionKey, serverPublicKeyBytes);// 4. 发送加密的会话密钥socket->write(encryptedSessionKey);// 5. 等待握手确认QString response = readString(socket);return response == "HANDSHAKE_OK";
}

系统登录界面

在这里插入图片描述

** SM2密钥协商过程日志**

在这里插入图片描述

用户注销后,会返回登录界面,此时用户已从服务器中下线。

3.2 安全文件传输系统

这个模块主要实现文件的安全传输,确保用户数据的安全性。同时,在这里使用了大量的Linux系统调用,尤其是文件调用。

3.2.1 文件上传功能

实现流程

  1. 用户选择文件
  2. 客户端使用SM4加密文件数据
  3. 计算文件SM3哈希值
  4. 分块传输到服务器
  5. 服务器解密并验证完整性

核心实现代码

// SM4文件加密 - FileTransfer类
bool FileTransfer::uploadFile(const QString& filepath) {QFile file(filepath);if (!file.open(QIODevice::ReadOnly)) return false;QByteArray fileData = file.readAll();// SM4加密QByteArray encryptedData = securityManager->encryptSM4(fileData);QJsonObject request;request["type"] = "upload";request["filename"] = QFileInfo(filepath).fileName();request["filesize"] = encryptedData.size();request["filehash"] = QString(securityManager->calculateSM3Hash(fileData).toHex());// 发送请求头socket->write(QJsonDocument(request).toJson());const int chunkSize = 8192;int bytesWritten = 0;while (bytesWritten < encryptedData.size()) {QByteArray chunk = encryptedData.mid(bytesWritten, chunkSize);int written = socket->write(chunk);bytesWritten += written;emit uploadProgress(bytesWritten, encryptedData.size());}return true;
}

文件管理界面

在这里插入图片描述

文件上传成功后,可以点击四个表头,以根据名称、类型、大小或上传时间对文件进行排序。点击一次为升序排序,再次点击则为降序排序。

在这里插入图片描述

服务器端文件接收日志

在这里插入图片描述

3.2.2 文件下载功能

实现要点

  • 用户权限验证(只能下载自己的文件)
  • SM4解密文件数据
  • 完整性校验

选择下载地址

在这里插入图片描述

服务器端发送文件日志

在这里插入图片描述

3.3 审计日志系统

3.3.1 日志记录架构

设计思路

  • 单例模式设计,线程安全
  • 多级别日志:DEBUG、INFO、WARNING、ERROR、CRITICAL
  • 多分类日志:SYSTEM、AUTH、CRYPTO、FILE_OP、DATABASE、NETWORK、SECURITY
  • 按用户和日期分离存储

核心实现代码

// 审计日志记录 - AuditLogger类
class AuditLogger {
public:enum LogLevel { DEBUG, INFO, WARNING, ERROR, CRITICAL };enum LogCategory { SYSTEM, AUTH, CRYPTO, FILE_OP, DATABASE, NETWORK, SECURITY };static AuditLogger& getInstance() {static AuditLogger instance;return instance;}void log(LogLevel level, LogCategory category, const QString& username, const QString& action, const QString& resource, bool success, const QString& details = "") {QMutexLocker locker(&logMutex);QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");QString logEntry = QString("[%1] [%2] [%3] %4: %5 on '%6' - %7 (%8)").arg(timestamp).arg(levelToString(level)).arg(categoryToString(category)).arg(username).arg(action).arg(resource).arg(success ? "SUCCESS" : "FAILED").arg(details);// 写入系统日志writeToSystemLog(logEntry);// 写入用户个人日志if (!username.isEmpty() && username != "SYSTEM") {writeToUserLog(username, logEntry);}}
};

3.3.2 用户日志下载

实现功能

  • 客户端可以下载自己的操作日志
  • 支持日期范围筛选
  • SM4加密传输确保安全

** 日志下载界面**

在这里插入图片描述
** 用户日志内容**

在这里插入图片描述
** 日志下载事件**

在这里插入图片描述

以下是你提供内容的润色和扩展版,保持结构清晰、语言规范,并适度增加技术细节和逻辑说明,适合用于实验报告:


4、其他功能

4.1 Socket编程

本系统采用基于 Qt 网络模块的 Socket 编程实现了客户端与服务器之间的可靠通信。

服务器端:
服务器端通过继承 QTcpServer 类,实现了基于 TCP 协议的监听与连接管理功能。当检测到新的客户端连接请求时,系统会自动创建一个独立的 ClientHandler 线程对象,专门负责处理该客户端的所有通信任务。此种“主线程监听 + 子线程处理”的结构设计,能够有效支持多客户端并发访问,显著提升了系统的并发处理能力与整体稳定性。

客户端:
客户端采用 QTcpSocket 实现与服务器的连接功能。通信模块被封装为 FileTransfer 类,统一管理网络连接的建立、文件数据的分片发送与接收、错误处理与状态监控等逻辑。该模块的封装提高了通信代码的可复用性与可维护性,使得客户端逻辑更加简洁明晰,便于后期拓展和维护。

服务器端关键实现:

class ServerCore : public QTcpServer {Q_OBJECTpublic:void start(quint16 port) {if (this->listen(QHostAddress::Any, port)) {qDebug() << "服务器启动,监听端口:" << port;} else {qDebug() << "服务器启动失败:" << this->errorString();}}protected:// 重写虚函数,处理新连接void incomingConnection(qintptr socketDescriptor) override {ClientHandler *handler = new ClientHandler(socketDescriptor, this);connect(handler, &QThread::finished, handler, &QObject::deleteLater);handler->start();  // 启动新线程处理客户端}
};

该设计模式通过将每个客户端请求交由独立线程处理,有效避免了主线程阻塞的问题,同时保障了系统在高并发情况下的稳定运行。

在这里插入图片描述


4.2 Linux系统调用支持

系统在文件操作模块中大量使用了基于 Qt 封装的 Linux 系统调用,确保文件传输的高效性与兼容性。文件的创建、写入、读取等底层操作均对应于实际的系统调用,如 openwritereadfsyncstat 等。

文件管理模块关键实现:

class FileManager {
public:// 文件创建和写入static bool saveFile(const QString& filepath, const QByteArray& data) {QFile file(filepath);QDir dir = QFileInfo(filepath).dir();if (!dir.exists()) {dir.mkpath(".");  // 等效于 mkdir}if (!file.open(QIODevice::WriteOnly)) {qDebug() << "文件创建失败:" << file.errorString();return false;}qint64 bytesWritten = file.write(data);  // 等效于 writeif (bytesWritten != data.size()) {qDebug() << "文件写入不完整";return false;}file.flush();  // 等效于 fsyncreturn true;}// 文件读取static QByteArray loadFile(const QString& filepath) {QFile file(filepath);if (!file.exists()) {  // 等效于 statqDebug() << "文件不存在:" << filepath;return QByteArray();}if (!file.open(QIODevice::ReadOnly)) {qDebug() << "文件打开失败:" << file.errorString();return QByteArray();}return file.readAll();  // 等效于 read}
};

4.3 身份鉴别及访问控制

系统在身份认证和访问控制方面引入了基于角色的权限管理机制。用户在登录时必须经过身份鉴别,认证成功后,系统会根据其账号信息为其分配对应的权限范围。普通用户仅能访问自己上传的文件,无法访问其他用户的数据,从而有效保障了数据的隔离性和安全性。

此外,为增强身份认证的安全性,系统采用口令加密存储机制,使用 SM3 哈希算法对用户口令进行摘要处理,并加入随机盐值(salt)进行混淆,以防止彩虹表攻击和哈希碰撞带来的威胁。认证流程在前后端之间通过安全通道进行,确保用户凭据在传输过程中不会被窃取或篡改。

这种精细化的访问控制策略不仅提升了系统的安全等级,也符合多用户环境下的文件管理需求。


二、安全性与密码完成以及完善过程

1、安全性设计与密码完成

1.1 SM3密码哈希存储机制

在这里插入图片描述

本系统在用户身份认证中采用SM3哈希与加盐机制提升安全性。用户注册时,系统生成32位随机盐值并与口令组合,使用SM3进行初始化哈希后执行1000轮迭代加密,最终将盐值与哈希结果组合存入数据库。登录时,系统提取存储的盐值和哈希,使用用户输入的口令重新执行相同的加密流程,最后将计算结果与数据库中的哈希值进行比对,以验证身份是否匹配,确保口令安全存储与验证的完整性。

SM3加密算法实现

QByteArray hashPasswordWithSalt(const QString& password, const QByteArray& salt = QByteArray()) {QByteArray actualSalt = salt.isEmpty() ? generateSalt() : salt;QByteArray combined = password.toUtf8() + actualSalt;// 多轮哈希 (PBKDF2 密钥拉伸)QByteArray hash = combined;const int rounds = 10000;  // 10000轮SM3哈希SM3_CTX ctx;uint8_t dgst[32];for (int i = 0; i < rounds; i++) {sm3_init(&ctx);sm3_update(&ctx, (const uint8_t*)hash.constData(), hash.size());sm3_finish(&ctx, dgst);hash = QByteArray((char*)dgst, 32);}// 返回 [32字节盐值] + [32字节哈希值]return actualSalt + hash;
}

1.2 混合密码系统实现

在这里插入图片描述

混合密码系统的实现流程从客户端启动开始。客户端首先生成一对SM2密钥(公钥和私钥),用于后续的密钥交换与加密通信。服务器端在启动时加载预先配置好的SM2密钥对,准备与客户端进行密钥协商。在连接建立后,服务器向客户端发送其SM2公钥,客户端接收后,结合自身私钥生成对称加密用的SM4会话密钥,并使用服务器公钥对该密钥加密后发送回服务器。
服务器接收到加密后的会话密钥后,使用自身的SM2私钥进行解密,从而获取SM4密钥,双方完成共享。为确保通信安全,系统在握手阶段进行确认,确保SM4密钥协商成功并一致,建立安全通信通道。每次通信会话系统都会生成独立的SM4密钥,并定期更新,降低长期使用带来的安全风险。
在数据传输过程中,客户端与服务器使用协商的SM4密钥进行加解密操作,确保数据传输的机密性与完整性。该混合密码机制结合SM2的密钥交换优势与SM4的高效对称加密能力,有效保障了通信过程中的数据安全。

1.2.1 SM2椭圆曲线密钥协商

  • 客户端密钥生成
void SecurityManager::generateSM2KeyPair() {if (sm2_key_generate(&clientSM2Key) != 1) {qDebug() << "SM2密钥对生成失败!";return;}// 提取64字节公钥 (x,y坐标各32字节)uint8_t public_key[64];if (sm2_z256_point_to_bytes(&clientSM2Key.public_key, public_key) == 1) {clientPublicKey = QByteArray((char*)public_key, 64);}
}
  • 服务器端密钥协商流程
bool performCryptoHandshake(QTcpSocket& socket) {// 1. 发送服务器SM2公钥if (!sendServerPublicKey(socket)) return false;// 2. 接收客户端加密的SM4会话密钥if (!receiveEncryptedSessionKey(socket)) return false;// 3. 发送握手确认handshakeCompleted = true;return true;
}

1.2.2 SM4对称加密系统

  • 会话密钥生成
void generateSessionKey() {// 生成128位(16字节)随机会话密钥sessionKey.resize(16);auto generator = QRandomGenerator::global();for (int i = 0; i < 16; i++) {sessionKey[i] = generator->bounded(256);}
}
  • 会话密钥生成

1.2.3 SM3完整性校验

  • 文件哈希计算
QString calculateHash(const QByteArray& data) {SM3_CTX ctx;uint8_t dgst[32];sm3_init(&ctx);sm3_update(&ctx, (const uint8_t*)data.constData(), data.size());sm3_finish(&ctx, dgst);return QByteArray((char*)dgst, 32).toHex();
}

1.3 SM4-CTR加密和SM3传输文件

在这里插入图片描述

本系统采用国密算法实现了文件在传输与存储过程中的双重安全保障。客户端首先利用 SM4 加密算法的计数器模式(CTR) 对文件内容进行加密。该模式具有良好的并行性和随机性,确保即使相同的明文也能生成不同的密文,从而有效防止内容泄露与模式分析。同时,客户端对原始文件数据计算其 SM3 摘要值,作为数据完整性的校验依据。
加密后的数据、生成的哈希值以及相关文件信息一并发送至服务器。服务器端接收到数据后,先用相同的会话密钥和初始化向量(IV)进行 SM4-CTR 解密,还原出原始数据内容。随后服务器重新计算一次该数据的 SM3 哈希值,并与客户端发送的哈希值进行比对。若两者一致,说明文件内容在传输过程中未被篡改,服务器则允许存入数据库;若不一致,则拒绝保存并报告完整性校验失败。
该机制实现了文件加密传输与可信存储的全流程防护,不仅保障了用户数据的机密性,也有效防止了数据被非法篡改或伪造的风险,特别适用于对数据安全要求较高的业务场景。


2、完善过程

问题1:SM2公钥生成全为零

问题现象

服务器生成的公钥全为零,即:

服务器公钥: 0000000000000000...(64字节全为0)

原因分析

错误的公钥提取方式,直接使用内存拷贝结构体,导致公钥数据不正确。

解决方案

修复前(错误)的代码如下:

memcpy(publicKey, &serverSM2Key.public_key, 64);

修复后(正确)的代码如下:

uint8_t public_key[64];
if (sm2_z256_point_to_bytes(&serverSM2Key.public_key, public_key) == 1) {serverPublicKey = QByteArray((char*)public_key, 64);
}

通过使用sm2_z256_point_to_bytes函数正确提取公钥数据,避免直接内存拷贝结构体的问题。

验证结果

修复后,服务器公钥正确生成,示例如下:

服务器公钥: "14a527b1d209d437854e67007648abbaddc00118df6c52191185a2ed0ccb85fd..."
64字节公钥正确生成

问题2 SM3密码杂凑算法

问题现象

常规的加密安全程度不够

解决方案

// 安全的密码存储方案
1. 生成32字节随机盐值
2. 密码+盐值组合
3. 进行10000轮SM3哈希运算
4. 存储格式:[盐值32字节][哈希32字节]

验证结果

输入测试密码: "707"
盐值长度: 32 内容: "0960b09cd073e238d6004605a217a8f6..."
开始 10000 轮哈希计算
最终结果长度: 64 内容: "0960b09cd073e238...9e8244c4dcd158494..."
10000轮哈希计算成功

问题3:SM2公钥生成全为零

问题现象
客户端在注册过程中出现无限等待服务器响应的情况。

原因分析

由于服务器错误地将注册请求当作登录请求处理,导致注册流程也尝试执行密钥协商。而注册过程中并不需要密钥协商,结果造成客户端在等待服务器发送SM2公钥的过程中陷入阻塞。

解决方案实现

// 在服务器端增加请求类型检测
void ServerCore::handleClientConnection(QTcpSocket* socket) {QString requestStr = readString(socket);QJsonObject obj = QJsonDocument::fromJson(requestStr.toUtf8()).object();QString requestType = obj["type"].toString();bool needsHandshake = true;if (requestType == "register") {needsHandshake = false; // 注册跳过密钥协商handleRegister(socket, obj);return;}if (needsHandshake) {if (!performServerHandshake(socket)) {socket->close();return;}}if (requestType == "login") {handleLogin(socket, obj);}
}

通过在服务器端添加对请求类型的判断,明确区分注册与登录请求,仅在登录请求中执行密钥协商,避免了不必要的SM2操作。

验证结果

检测到请求类型: "register"
检测到注册请求,跳过密钥协商,直接处理注册
注册流程正常
登录密钥协商正常

问题4:多线程数据库连接冲突

问题现象
在多客户端并发访问的场景下,服务器端的数据库操作偶尔失败,表现为无法打开数据库或数据读写异常。

原因分析
Qt 中的 QSqlDatabase 对象在多线程环境下不具备线程安全性,若多个线程共用一个数据库连接,会导致连接冲突或资源竞争,从而导致数据库操作失败。

解决方案实现

// 为每个线程创建独立的数据库连接
QString dbName = "server_thread_" + QString::number((quintptr)QThread::currentThreadId());
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", dbName);
db.setDatabaseName("server.db");if (!db.open()) {qDebug() << "线程" << QThread::currentThreadId() << "数据库连接失败";return false;
}

通过为每个线程指定唯一的连接名,避免不同线程共享同一数据库连接,有效解决并发冲突问题。

验证结果

线程ID: 0x16c 打开数据库成功
线程ID: 0x1a0 打开数据库成功
多线程并发访问数据库正常,未再出现连接失败或写入异常

三、项目改动和未来打算

在完成基础系统功能开发后,我认真评估了现有成果的优缺点,并结合实际开发体验与系统运行情况,未来可能从以下方面对系统进行完善:

1. 文件管理功能完善

  • 文件重命名:支持用户修改文件名,避免重名冲突并更新数据库索引。
  • 文件夹与目录结构支持:引入“文件夹”概念,实现基本层级目录管理,使用户在面对大量文件时能更好地分类和管理。

2. 搜索与筛选功能

  • 模糊搜索:支持文件名模糊匹配查询;
  • 组合查询:可支持同时输入多个关键词、按多个维度联合筛选。

3. 批量操作与交互优化

  • 多文件批量上传与下载:通过文件选择器支持多选,并在传输队列中统一管理;
  • 批量删除与分享:支持选中多个文件同时进行删除、生成分享链接等操作;
  • 文件上传/下载进度条优化:提供总进度、剩余时间等信息提示,改善用户等待体验。

4. 文件加密与验证机制强化

  • 当前系统采用SM4加密和SM3哈希作为基础安全手段;
  • 后续可尝试引入“数字签名 + 时间戳”机制,防止篡改与伪造;
  • 若部署于多用户系统,可考虑对每个用户使用独立密钥进行文件加密。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/86307.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年- H76-Lc184--55.跳跃游戏(贪心)--Java版

1.题目描述 2.思路 只要是在最大覆盖范围覆盖了&#xff0c;就是覆盖了。 局部最优&#xff1a;每遍历一个元素取它最大的覆盖范围 全局最优&#xff1a;在这个序列里&#xff0c;可以得到最大的覆盖范围。如果覆盖范围能达到最后一个元素&#xff0c;就是全局最优 &#xff0…

05.查询表

查询表 字段显示可以使用别名: col1 AS alias1, col2 AS alias2, … WHERE子句:指明过滤条件以实现“选择"的功能: 过滤条件: 布尔型表达式算术操作符:,-,*,/,%比较操作符:,<>(相等或都为空),<>,!(非标准SQL),>,>,<,<范围查询: BETWEEN min_num …

Python学习——数组的行列互换

数组的行列互换 data [ [col for col in range (4)] for row in range (4)] for row in data: print (row) print(“--------------”) for r_index,row in enumerate(data): for c_index in range (r_index,len(row)): tmp data [c_index] [r_index] data[c_index] [r_index…

bugku 应急加固1

Linux的应急加固 一、JS劫持 获取JS劫持域名 JS劫持&#xff0c;JavaScript Hijacking介绍&#xff1a; 攻击者通过某种方式篡改网页中的JavaScript代码&#xff0c;从而使网页跳转到恶意域名。 常见攻击方式有&#xff1a; 中间人攻击&#xff0c;在网络传输过程中拦截并修…

ant-design4.xx实现数字输入框; 某些输入法数字需要连续输入两次才显示

目录 一、问题 二、解决方法 三、总结 一、问题 1.代码里有一个基于ant封装的公共组件数字输入框&#xff0c;测试突然说 无效了&#xff0c;输入其他字符也会显示&#xff1b;改了只有又发现某些 输入法 需要连续输入两次 才能显示出来。 二、解决方法 1.就离谱&#xff0…

郑州工程技术学院赴埃文科技开展访企拓岗促就业活动

6 月 3 日&#xff0c;郑州工程技术学院信息工程学院&软件学院党总支书记尚德基、校企合作处处长吴博、软件学院院长叶恺、信息工程学院院长马耀锋、副院长黄继海、河南省人工智能产业创新发展联盟执行秘书长孟松涛等领导一行到访郑州埃文科技有限公司。埃文科技总经理助理…

pandas 字符串存储技术演进:从 object 到 PyArrow 的十年历程

文章目录 1. 引言2. 阶段1&#xff1a;原始时代&#xff08;pandas 1.0前&#xff09;3. 阶段2&#xff1a;Python-backed StringDtype&#xff08;pandas 1.0 - 1.3&#xff09;4. 阶段3&#xff1a;PyArrow初次尝试&#xff08;pandas 1.3 - 2.1&#xff09;5. 阶段4&#xf…

[特殊字符] 在 React Native 项目中封装 App Icon 一键设置命令(支持参数与默认路径)

📦 前置依赖 使用的是社区维护的 CLI 工具: @bam.tech/react-native-make它扩展了 react-native 命令,支持 set-icon 功能。 安装: yarn add -D "@bam.tech/react-native-make"🧠 封装目标 我们希望能够通过以下方式调用: # 默认使用 ./icon.png yarn …

[论文阅读] 人工智能 | 搜索增强LLMs的用户偏好与性能分析

【论文解读】Search Arena&#xff1a;搜索增强LLMs的用户偏好与性能分析 论文信息 作者: Mihran Miroyan, Tsung-Han Wu, Logan King等 标题: Search Arena: Analyzing Search-Augmented LLMs 来源: arXiv preprint arXiv:2506.05334v1, 2025 一、研究背景&#xff1a;…

[2025CVPR]确定性图像转换新突破:双逼近器布朗桥模型(Dual-approx Bridge)技术详解

本文深入解析CVPR 2024顶会论文《Deterministic Image-to-Image Translation via Denoising Brownian Bridge Models with Dual Approximators》,揭示确定性图像转换的核心突破 一、问题背景:确定性图像转换的挑战 在图像转换任务中(如超分辨率、医学影像处理),​确定性…

Python Pytest

1.Pytest用例发现规则 1.1 模块名(python文件)名必须以 test_ 开头或 _test 结尾&#xff0c;如 test_case&#xff0c;case_test&#xff0c;下划线都不能少 1.2 模块不能放在 . 开头的隐藏目录或者叫 venv的目录下&#xff0c;virtual environment&#xff0c;叫venv1都可以…

CSRF(跨站请求伪造)详解

目录 一、&#x1f4d6;什么是CSRF 二、&#x1f517;漏洞利用过程 三、&#x1f4d1;漏洞的前提条件 四、&#x1f50d;常见漏洞发生位置 五、✅CSRF挖掘技巧 (一) 抓正常请求包进行初步判断 (二) Referer 绕过验证测试 (三) Token 缺失与二次验证缺失识别 六、⚠️漏…

深入解析 Qwen3-Embedding 的模型融合技术:球面线性插值(Slerp)的应用

在深度学习领域&#xff0c;模型融合技术是一种强大的工具&#xff0c;用于提升模型的鲁棒性和泛化能力。通过结合多个模型的优势&#xff0c;可以减少单一模型的过拟合风险&#xff0c;并在多种任务中实现更优的性能表现。在 Qwen3-Embedding 的训练过程中&#xff0c;模型融合…

【在线五子棋对战】二、websocket 服务器搭建

文章目录 Ⅰ. WebSocket1、简介2、特点3、原理解析4、报文格式 Ⅱ. WebSocketpp1、认识2、常用接口3、websocketpp库搭建服务器搭建流程主体框架填充回调函数细节 4、编写 makefile 文件5、websocket客户端 Ⅰ. WebSocket 1、简介 WebSocket 是从 HTML5 开始支持的一种网页端…

针对异构数据的联邦学习

在联邦学习中&#xff0c;数据异构性是指不同客户端之间的数据分布差异&#xff0c;包括数据的特征空间、标签空间以及数据量等方面的差异。处理异构数据是联邦学习中的一个重要挑战&#xff0c;因为异构数据可能导致模型训练过程中的性能不稳定、收敛速度较慢&#xff0c;甚至…

【判断自整除数】2022-4-6

缘由是判断自整除数的&#xff0c;这个我的结果是正确的&#xff0c;但是提交就有运行错误是怎么回事啊-编程语言-CSDN问答 void 自整除数字() {//所谓的自整除数字就是该数字可以整除其每一个位上的数字。 //对一个整数n,如果其各个位数的数字相加得到的数m能整除n,则称n为自…

@Import原理与实战

文章目录 前言一、导入普通类二、导入ImportSelector实现类三、导入ImportBeanDefinitionRegistrar实现类四、Import注解的解析4.1、解析实现ImportSelector的候选bean4.2、解析实现ImportBeanDefinitionRegistrar的候选bean4.3、DeferredImportSelector的特殊处理 总结 前言 I…

day 18进行聚类,进而推断出每个簇的实际含义

浙大疏锦行 对聚类的结果根据具体的特征进行解释&#xff0c;进而推断出每个簇的实际含义 两种思路&#xff1a; 你最开始聚类的时候&#xff0c;就选择了你想最后用来确定簇含义的特征&#xff0c; 最开始用全部特征来聚类&#xff0c;把其余特征作为 x&#xff0c;聚类得到…

Java并发编程实战 Day 11:并发设计模式

【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天&#xff0c;今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案&#xff0c;它们不仅提供了优雅的设计思路&#xff0c;还能显著提升系统的性能…

iview组件库:当后台返回到的数据与使用官网组件指定的字段不匹配时,进行修改某个属性名再将response数据渲染到页面上的处理

1、需求导入 当存在前端需要的数据的字段渲染到表格或者是一些公共的表格组件展示数据时的某个字段名与后台返回的字段不一致时&#xff0c;那么需要前端进行稍加处理&#xff0c;而不能直接this.list res.data;这样数据是渲染不出来的。 2、后台返回的数据类型 Datalist(pn) …