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

七、网络安全-企业数据脱敏

文章目录

  • 前言
  • 一、数据脱敏方法
  • 二、企业脱敏方案
    • 1. 数据库脱敏方案
    • 2. 历史数据脱敏
    • 3. 具体实现
  • 三、日志脱敏方案
  • 四、输出脱敏


前言

数据脱敏

  随着用户对个人隐私数据的重视和法律法规的完善,数据安全显得愈发重要。一方面可以加强权限管理,减少能够接触数据的人员以及导出数据加强审批。另一方面,还需要从技术上对用户隐私数据进行脱敏处理,提高数据的安全性。


一、数据脱敏方法

  数据脱敏方法有很多种,大致可以按照以下进行分类:

  • 隐藏法: 只显示敏感信息的部分内容,其他部分进行遮挡,比较常见使用星号替代。这种方式日常比较多见,比如手机号,银行卡号等只显示后面和后面几位,好处是虽然只是部分内容显示,但足够提供有效信息,同时不会暴露完整数据。
  • 混淆法: 对原有数据截断、替换、隐藏、数字进行随机移位,使得原有数据完全失真或者部分失真,混淆真假。
  • 加密:通过加密密钥和算法对敏感数据进行加密得到密文,密文可见但是完全没有可读意义,是脱敏最彻底的方法。其中对称加密还能密钥解密可以从密文恢复原始数据。比如密码保存采用非对称加密,手机号存储时采用对称加密。

  用户的敏感数据包含姓名、电话号码、身份证、银行卡号、电子邮件、家庭住址、登录密码等等。需要考虑数据的敏感程度、数据安全要求以及实际业务使用场景选择合适的脱敏方法。Hutool包里面提供了许多常用的脱敏方法。

二、企业脱敏方案

  企业如何实现脱敏?
  我们先来看典型的系统数据交互链路,数据需要经过数据库、后端应用、前端(PC\移动端)。

系统数据交互链路

  • 数据库侧: 数据库保存了原始数据,有权限人员可以查看数据和导出数据。
  • 后端应用内: 后端应用中会打印相关日志,数据通过日志存储下来。通过日志,能够得到原始数据。
  • 应用输出: 前端能够从后端读取到原始数据。

1. 数据库脱敏方案

根据业务具体要求选择合适脱敏方法。

  1. 脱敏地点可以在应用中手动脱敏,当然这种方法不常用,改动点多对业务侵入大。
  2. 另外一种方案在ORM框架中修改sql实现,其中mybatis框架为java后端系统中最常用的框架。mybatis自带拦截器扩展,允许在映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
  • Executor: 拦截执行器的方法,例如 update、query、commit、rollback 等。可以用来实现缓存、事务、分页等功能。
  • ParameterHandler: 拦截参数处理器的方法,例如 setParameters 等。可以用来转换或加密参数等功能。
  • ResultSetHandler: 拦截结果集处理器的方法,例如 handleResultSets、handleOutputParameters 等。可以用来转换或过滤结果集等功能。
  • StatementHandler: 拦截语句处理器的方法,例如 prepare、parameterize、batch、update、query 等。可以用来修改 SQL 语句、添加参数、记录日志等功能。

Mybatis执行流程

2. 历史数据脱敏

数据库脱敏另外一个问题是历史数据问题。历史原因最开始的技术方案保存明文,所以脱敏时需要做到平滑脱敏。要做到平滑脱敏,可按照如下流程:

  • 新增脱敏字段: 在源表上新增脱敏字段。
  • 数据双写: 源字段和脱敏字段都写入数据。
  • 历史数据迁移: 历史数据迁移,刷入脱敏字段。
  • 读取脱敏字段: 从脱敏字段读取数据返回。
  • 清空源字段: 确保所有流程都正确的情况下,清空源字段。

3. 具体实现

本文mybatis实现数据库加解密为例。

1.表里面新增脱敏字段。

示例中脱敏新字段格式规范为源字段添加Encrypt后缀。vo里面添加脱敏注解标记

public class Employee {private Long id;private String name;@EncryptTagprivate String mobile;private String mobileEncrypt;private String email;private double salary;
} 

2.实现自定义拦截。

/***
** 加密拦截
***/
@Intercepts({@Signature(type = Executor.class,method = "update",args = {MappedStatement.class, Object.class}
), @Signature(type = Executor.class,method = "query",args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}
), @Signature(type = Executor.class,method = "query",args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
)})
public class EncryptPlugin implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {MappedStatement mappedStatement = (MappedStatement)invocation.getArgs()[0];Object param = invocation.getArgs()[1];PluginService.encrypt(invocation, param);return invocation.proceed();}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {}
}/***
** 解密拦截
***/
@Intercepts({@Signature(type = ResultSetHandler.class,method = "handleResultSets",args = {Statement.class}
)})
public class DecryptPlugin implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {Object result = invocation.proceed();if (result != null && result instanceof List) {this.decrypt(((List) result).iterator());}return result;}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {}private void decrypt(Iterator iterator) throws Throwable {while(iterator.hasNext()) {Object object = iterator.next();PluginService.decrypt(object);}}
}

3.实现sql修改,完成加解密逻辑。

public class PluginService {private static final Logger LOGGER = LoggerFactory.getLogger(PluginService.class);private static final Map<String, List<Field>> ENCRYPT_TAG_FIELDS = new ConcurrentHashMap();public static void encrypt(Invocation invocation, Object object) throws Throwable {if (object.getClass().isArray()) {int length = Array.getLength(object);if (length <= 0) {return;}for (int i = 0; i < length; ++i) {encryptSingleObject(Array.get(object, i));}} else if (object instanceof Collection) {Collection collection = (Collection) object;Iterator itr = collection.iterator();while (itr.hasNext()) {Object item = itr.next();encryptSingleObject(item);}} else {encryptSingleObject(object);}}private static void encryptSingleObject(Object object) throws Throwable {if (object != null) {String className = object.getClass().getName();List<Field> EncryptTagFields = ENCRYPT_TAG_FIELDS.get(className);if (EncryptTagFields == null) {EncryptTagFields = findEncryptTagFields(object);ENCRYPT_TAG_FIELDS.putIfAbsent(className, EncryptTagFields);}encryptFields(object, EncryptTagFields);}}private static void encryptFields(Object object, List<Field> EncryptTagFields) throws Throwable {if (object != null && !EncryptTagFields.isEmpty()) {String[] originalValues = new String[EncryptTagFields.size()];for(int i = 0; i < EncryptTagFields.size(); ++i) {Field field = (Field)EncryptTagFields.get(i);String value = (String)field.get(object);originalValues[i] = value;}for(int i = 0; i < EncryptTagFields.size(); ++i) {Field field = (Field)EncryptTagFields.get(i);String value = originalValues[i];if (value == null) {continue;}Field encryptField = getEncryptField(object, field);if (encryptField == null) {continue;}String encryptValue = encryptFieldValue(value);encryptField.set(object, encryptValue);field.set(object, null);}}}private static String encryptFieldValue(String value) {String encryptValue = value + "encrypt";return encryptValue;}public static void decrypt(Object object) throws Throwable {if (object == null) {return;}String className = object.getClass().getName();List<Field> encryptTagFields = ENCRYPT_TAG_FIELDS.get(className);if (encryptTagFields == null) {encryptTagFields = findEncryptTagFields(object);ENCRYPT_TAG_FIELDS.putIfAbsent(className, encryptTagFields);}decryptFields(object, encryptTagFields);}private static void decryptFields(Object object, List<Field> encryptTagFields) throws Throwable {if (encryptTagFields.isEmpty()) {return;}for (int i = 0; i < encryptTagFields.size(); ++i) {Field field = encryptTagFields.get(i);Field encryptField = getEncryptField(object, field);Object fieldValue = encryptField.get(object);if (fieldValue == null) {continue;}if (fieldValue instanceof String) {String value = (String) fieldValue;value = AesUtil.decrypt(value);field.set(object, value);encryptField.set(object, null);}}}private static List<Field> findEncryptTagFields(Object object) {Class clazz = object.getClass();List<Field> fieldList = new ArrayList<>();for(; clazz != null; clazz = clazz.getSuperclass()) {Field[] declaredFields = clazz.getDeclaredFields();int length = declaredFields.length;for(int index = 0; index < length; ++index) {Field field = declaredFields[index];if (field.getAnnotation(EncryptTag.class) != null) {if (field.getType() == String.class) {field.setAccessible(true);fieldList.add(field);} else {LOGGER.error("@EncryptTag should be used on String field. class: {}, fieldName: {}", clazz.getName(), field.getName());}}}}return fieldList;}private static Field getEncryptField(Object object, Field field) throws Exception {String encryptFieldName = AesUtil.encrypt(field.getName());Field encyptField = getField(object, encryptFieldName);if (encyptField == null) {throw new Exception(object.getClass() + "对象没有对应的加密字段:" + encryptFieldName);} else {encyptField.setAccessible(true);return encyptField;}}public static Field getField(Object object, String fieldName) {for(Class clazz = object.getClass(); clazz != null; clazz = clazz.getSuperclass()) {Field[] var3 = clazz.getDeclaredFields();int var4 = var3.length;for(int var5 = 0; var5 < var4; ++var5) {Field field = var3[var5];if (field.getName().equals(fieldName)) {return field;}}}return null;}
}

三、日志脱敏方案

  日志脱敏,核心在于序列化时对于敏感字段修改其序列化方式。各大序列化工具一般都有序列化自定义功能,本文以fastjson为例讲解实现,实现方式有两种:

  1. 基于注解@JSONField实现:不建议使用,对业务入侵太大。
  2. 基于序列化过滤器:建议使用,fastjson提供了多种SerializeFilter:
  • PropertyPreFilter:根据PropertyName判断是否序列化
  • PropertyFilter:根据PropertyName和PropertyValue来判断是否序列化
  • NameFilter:修改Key,如果需要修改Key,process返回值则可
  • ValueFilter:修改Value
  • BeforeFilter:序列化时在最前添加内容
  • AfterFilter:序列化时在最后添加内容

通过实现ValueFilter自定义序列化扩展,针对目标类以及字段进行脱敏返回。

核心代码简化如下:

public class FastjsonValueFilter implements ValueFilter {@Overridepublic Object process(Object object, String name, Object value) {if (needDesensitize(object, name)) {return desensitize(value);}}
}
String s = JSON.toJSONString(new Person("131xxxx1552","123@163.com"),new FastjsonValueFilter());

在标记脱敏字段以及对应方法时,可以通过配置的方法, 对类相关的脱敏字段以及方法进行封装。

要求不高的话添加响应的注解也可实现。

四、输出脱敏

  在输出层织入切面进行拦截,在切面内实现脱敏逻辑。实现逻辑跟日志脱敏类似,需要对脱敏字段进行标记以及对应脱敏方法。

如果是Spring Boot集成,配置 Spring MVC 的话只需继承 WebMvcConfigurer 覆写 configureMessageConverters方法,支持全局和指定类脱敏配置,示例如下::

@Configuration
public class FastJsonWebSerializationConfiguration implements WebMvcConfigurer {@Bean(name = "httpMessageConverters")public HttpMessageConverters fastJsonHttpMessageConverters() {// 1.定义一个converters转换消息的对象FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();// 2.添加fastjson的配置信息,比如: 是否需要格式化返回的json数据FastJsonConfig fastJsonConfig = new FastJsonConfig();fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);// 中文乱码解决方案List<MediaType> mediaTypes = new ArrayList<>();//设定json格式且编码为UTF-8mediaTypes.add(MediaType.APPLICATION_JSON_UTF8);fastConverter.setSupportedMediaTypes(mediaTypes);//添加全局自定义脱敏fastJsonConfig.setSerializeFilters(new ValueDesensitizeFilter());//添加指定类脱敏方法Map<Class<?>, SerializeFilter> classSerializeFilters = new HashMap<>();classSerializeFilters.put(Employee.class, new FastjsonValueFilter());fastJsonConfig.setClassSerializeFilters(classSerializeFilters);// 3.在converter中添加配置信息fastConverter.setFastJsonConfig(fastJsonConfig);// 4.将converter赋值给HttpMessageConverterHttpMessageConverter<?> converter = fastConverter;// 5.返回HttpMessageConverters对象return new HttpMessageConverters(converter);}
}

本文的引用仅限自我学习如有侵权,请联系作者删除。
参考知识
详解企业级数据脱敏方案


相关文章:

七、网络安全-企业数据脱敏

文章目录 前言一、数据脱敏方法二、企业脱敏方案1. 数据库脱敏方案2. 历史数据脱敏3. 具体实现 三、日志脱敏方案四、输出脱敏 前言 数据脱敏‌ 随着用户对个人隐私数据的重视和法律法规的完善&#xff0c;数据安全显得愈发重要。一方面可以加强权限管理&#xff0c;减少能够接…...

电子应用设计方案-62:智能鞋柜系统方案设计

智能鞋柜系统方案设计 一、引言 随着人们生活水平的提高&#xff0c;对家居用品的智能化需求也日益增加。智能鞋柜作为一种创新的家居产品&#xff0c;能够有效地解决鞋子的收纳、消毒、除臭和保养等问题&#xff0c;为用户提供更加便捷和健康的生活体验。 二、系统概述 1. 系…...

C++ 引用的基本用法

通过使用引用&#xff0c;可以创建该对象的另一个名字&#xff0c;而不会引入额外的内存开销。引用在函数参数传递、返回值以及避免拷贝大型对象时特别有用。 引用的基本用法 创建引用&#xff1a; 引用必须在创建时被初始化&#xff0c;且一旦被绑定到一个对象后&#xff0…...

全面解析 Golang Gin 框架

1. 引言 在现代 Web 开发中&#xff0c;随着需求日益增加&#xff0c;开发者需要选择合适的工具来高效地构建应用程序。对于 Go 语言&#xff08;Golang&#xff09;开发者来说&#xff0c;Gin 是一个备受青睐的 Web 框架。它轻量、性能高、易于使用&#xff0c;并且具备丰富的…...

element plus的table组件,点击table的数据是,会出现一个黑色边框

在使用 Element Plus 的 Table 组件时&#xff0c;如果你点击表格数据后出现了一个黑色边框&#xff0c;这通常是因为浏览器默认的焦点样式&#xff08;outline&#xff09;被触发了。如图&#xff1a; 你可以通过自定义 CSS 来隐藏这个黑色边框&#xff0c;代码如下&#xff1…...

三种国产大语言模型Python免费调用

基础三大模型&#xff0c;需要先去官方注册获得key&#xff1b;后续可以使用下列代码调用 1.腾讯 安装&#xff1a; pip install -i https://mirrors.tencent.com/pypi/simple/ --upgrade tencentcloud-sdk-python 实例&#xff1a; import jsonimport typesfrom tencentcl…...

Ansible playbook 详解与实战操作

一、概述 playbook 与 ad-hoc 相比,是一种完全不同的运用 ansible 的方式&#xff0c;类似与 saltstack 的 state 状态文件。ad-hoc 无法持久使用&#xff0c;playbook 可以持久使用。 playbook 是由一个或多个 play 组成的列表&#xff0c;play 的主要功能在于将事先归并为一…...

linux普通用户使用sudo不需要输密码

1.root用户如果没有密码&#xff0c;先给root用户设置密码 sudo passwd root #设置密码 2.修改visudo配置 su #切换到root用户下 sudo visudo #修改visudo配置文件 用户名 ALL(ALL) NOPASSWD: ALL #下图所示处新增一行配置 用户名需要输入自己当前主机的用户名...

linux-----数据库

Linux下数据库概述 数据库类型&#xff1a; 关系型数据库&#xff08;RDBMS&#xff09;&#xff1a;如MySQL、PostgreSQL、Oracle等。这些数据库以表格的形式存储数据&#xff0c;表格之间通过关系&#xff08;如主键 - 外键关系&#xff09;相互关联。关系型数据库支持复杂的…...

【Linux进程】进程间的通信

目录 1. 进程间通信 1.1 进程间通信的目的 2. 管道 2.1 什么是管道 2.2. 匿名管道 匿名管道的特性 管道的4种情况 联系shell中的管道 2.3. 命名管道 代码级建立命名管道 2.4. 小结 总结 1. 进程间通信 进程间通信&#xff08;Inter-Process Communication&#xff0c;IPC&…...

面试题整理4----lvs,nginx,haproxy区别和使用场景

LVS、Nginx、HAProxy&#xff1a;区别与使用场景 1. LVS&#xff08;Linux Virtual Server&#xff09;1.1 介绍1.2 特点1.3 使用场景 2. Nginx2.1 介绍2.2 特点2.3 使用场景 3. HAProxy3.1 介绍3.2 特点3.3 使用场景 4. 总结对比 在构建高可用、高性能的网络服务时&#xff0c…...

开放词汇目标检测(Open-Vocabulary Object Detection, OVOD)综述

定义 开放词汇目标检测&#xff08;Open-Vocabulary Object Detection, OVOD&#xff09;是一种目标检测任务&#xff0c;旨在检测和识别那些未在训练集中明确标注的物体类别。传统的目标检测模型通常只能识别有限数量的预定义类别&#xff0c;而OVOD模型则具有识别“开放词汇…...

Python读写JSON文件

import jsondef writeJSONFile(self):with open(g_updateFilePath, "w" encodingutf-8) as fiel:json.dump(dictData, fiel, indent4, ensure_asciiFalse)fiel.close()def readJsonToDict(file):with open(file, r, encodingutf-8) as f: # 确保文件以 UTF-8 编码打…...

使用Python开发高级游戏:创建一个3D射击游戏

在这篇文章中,我们将深入介绍如何使用Python开发一个简单的3D射击游戏。我们将使用Pygame库来创建2D游戏界面,并结合PyOpenGL来进行3D渲染。这个项目的目标是帮助你理解如何将2D和3D图形结合起来,创建更复杂的游戏机制,包括玩家控制、敌人AI、碰撞检测和声音效果。 一、开…...

springboot 配置Kafka 关闭自启动连接

这里写自定义目录标题 springboot 配置Kafka 关闭自启动连接方法一&#xff1a;使用 ConditionalOnProperty方法二&#xff1a;手动管理Kafka监听器容器方法三&#xff1a;使用 autoStartupfalse结语 springboot 配置Kafka 关闭自启动连接 在Spring Boot应用程序中&#xff0c…...

Jenkins中添加节点实战

Jenkins是一个开源的自动化服务器,用于持续集成和持续交付(CI/CD)。为了提高构建和测试的效率,我们可以在Jenkins中添加节点(也称为代理或从属节点)。本文将详细介绍如何在Jenkins中添加节点,包括安装Java 11、Git、设置凭证、多种配置Jenkins Agent的方法以及验证。 &#…...

DL作业11 LSTM

习题6-4 推导LSTM网络中参数的梯度&#xff0c; 并分析其避免梯度消失的效果 LSTM&#xff08;长短期记忆网络&#xff09;是一种特殊的循环神经网络&#xff08;RNN&#xff09;&#xff0c;旨在解决普通 RNN 在处理长序列时遇到的梯度消失和梯度爆炸问题。它通过设计多个门…...

用 Python 实现井字棋游戏

一、引言 井字棋&#xff08;Tic-Tac-Toe&#xff09;是一款经典的两人棋类游戏。在这个游戏中&#xff0c;玩家轮流在 3x3 的棋盘上放置自己的标记&#xff0c;通常是 “X” 和 “O”&#xff0c;第一个在棋盘上连成一线&#xff08;横、竖或斜&#xff09;的玩家即为获胜者。…...

构建MacOS应用小白教程(打包 签名 公证 上架)

打包 在package.json中&#xff0c;dependencies会被打进 Electron 应用的包里&#xff0c;而devDependencies则不会&#xff0c;所以必要的依赖需要放到dependencies中。files中定义自己需要被打进 Electron 包里的文件。以下是一个完整的 mac electron-builder的配置文件。 …...

如何高效使用 Facebook Business Manager (商务管理平台)

在数字营销的浪潮中&#xff0c;Facebook Business Manager&#xff08;商务管理平台&#xff09;已成为众多企业管理社交广告活动、品牌资产和团队协作的核心工具。无论你是刚刚进入社交广告领域的小型企业主&#xff0c;还是经验丰富的大型品牌经理&#xff0c;掌握 Facebook…...

每天学习一个思维模型 - 损失规避

定义 损失规避&#xff08;Loss aversion&#xff09;&#xff0c;又称损失厌恶&#xff0c;指人们面对同样数量的利益和损失时&#xff0c;认为损失更加令他们难以忍受。损失带来的负效用为收益正效用的2至2.5倍。损失厌恶反映了人们的风险偏好并不是一致的&#xff0c;当涉及…...

Python知识分享第三十一天-Numpy和Pnadas入门

NumPy Numpy介绍 Numpy是Python中科学计算的基础包,它是一个Python库提供多维数组对象 各种派生对象(如掩码数组和矩阵),以及用于对数组进行快速的各种例程,包括数学 ,逻辑, 形状操作,排序,选择,I/O,离散傅里叶变换,基本线性代数,基本统计运算,随机模拟等等(Numpy的核心是nda…...

mlr3超参数Hyperparameter 自动寻找auto

底层还是根据你本来在R跑单独那一个机器学习的函数&#xff0c;例如randomForest::randomForest()&#xff0c;里面可以填入什么&#xff0c;然后跟你的实际数据取值范围去设个范围。然后用auto_tuner()函数对学习器的超参数自动调参 随机森林randomforest learner_rf <- …...

双臂机器人

目录 一、双臂机器人简介 二、双臂机器人系统的组成 三、双臂机器人面临的主要挑战 3.1 协调与协同控制问题 3.2 力控制与柔顺性问题 3.3 路径规划与轨迹优化问题 3.4 感知与环境交互 3.5 人机协作问题 3.6 能源与效率问题 3.7 稳定性与可靠性问题 四、双臂机器人…...

MATLAB中cvx工具箱的使用

CVX 是 MATLAB 中一个用于解决凸优化问题的建模工具箱。它使得定义、求解和分析凸优化问题变得简单。CVX 允许用户用类似数学表达的方式编写凸优化问题&#xff0c;而不需要过多关注底层的优化算法。CVX 的核心功能是将一个简单的数学问题转化为 MATLAB 可以理解并求解的标准形…...

EGO Swarm翻译

目录 摘要 Ⅰ 介绍 Ⅱ 相关工作 A . 单四旋翼局部规划 B . 拓扑规划 C. 分布式无人机集群 Ⅲ 基于梯度的局部规划隐式拓扑轨迹生成 A.无需ESDF梯度的局部路径规划 B.隐式拓扑轨迹生成 Ⅳ 无人机集群导航 A 机间避碰 B. 定位漂移补偿 C. 从深度图像中去除agent Ⅴ …...

Webpack简单介绍及安装

一、介绍 Webpack 是一个现代 JavaScript 应用程序的静态模块打包器&#xff08;module bundler&#xff09;。它将应用程序中的所有依赖项&#xff08;JavaScript、图片、CSS 等&#xff09;打包成一个或多个 bundle。这样做的主要目的是减少加载时间和提高应用程序的加载性能…...

如何在Anaconda的虚拟环境中下载Python包

一、首先查看conda下的虚拟环境 使用conda info -e查看当前conda下的虚拟环境&#xff1a; conda info -e 二、激活要添加Python包的虚拟环境 其中base是基础环境&#xff0c;这里我们选择conda_env这个虚拟环境 conda activate conda_env 三、使用conda命令安装需要的Pyth…...

React 事件机制和原生 DOM 事件流有什么区别

发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【宝藏入口】。 React 的事件机制与原生 DOM 事件流在设计和实现上有一些显著的区别。了解这些区别有助于我们更好地理解 React 是如何管理事件的…...

React 底部加载组件(基于antd)

底部加载组件的意义在于提供一种流畅的用户体验&#xff0c;以便在用户滚动到页面底部时自动加载更多内容。这样可以让用户无需离开当前页面&#xff0c;就能够无缝地浏览更多的内容.通过底部加载组件&#xff0c;可以分批加载页面内容&#xff0c;减少一次性加载大量数据对页面…...

Redis应用—7.大Value处理方案

1.⽅案设计 步骤一&#xff1a;首先需要配置一个crontab定时调度shell脚本&#xff0c;然后该脚本每天凌晨会通过rdbtools⼯具解析Redis的RDB⽂件&#xff0c;接着对解析出的内容进行过滤&#xff0c;把RDB⽂件中的⼤key导出到CSV⽂件。 步骤二&#xff1a;使⽤SQL导⼊CSV⽂件到…...

洛谷P2742 圈奶牛 (凸包 Andrew算法)

[USACO5.1] 圈奶牛Fencing the Cows /【模板】二维凸包 题目背景 upd: 新增一组 hack 数据。 题目描述 农夫约翰想要建造一个围栏用来围住他的奶牛&#xff0c;可是他资金匮乏。他建造的围栏必须包括他的奶牛喜欢吃草的所有地点。对于给出的这些地点的坐标&#xff0c;计算…...

Spring(一)---IOC(控制权反转)

目录 引入 1.什么叫IOC(Inversion of Control)控制权反转&#xff1f; 2.什么叫AOP(Aspect-Oriented Programming)面向切面编程(涉及Java代理)&#xff1f; 3.简单谈一下Java怎么实现ICO? Spring框架的介绍 1. Spring框架的概述 2. Spring框架的优点 Spring IOC容器介绍…...

MySQL数据库——门诊管理系统数据库数据表

门诊系统数据库his 使用图形化工具或SQL语句在简明门诊管理系统数据库his中创建数据表&#xff0c;数据表结构见表2-3-9&#xff5e;表2-3-15所示。 表2-3-9 department&#xff08;科室信息表&#xff09; 字段名称 数据类型 长度 是否为空 说明 dep_ID int 否 科室…...

linux环境使用yum方式安装nginx

linux环境使用yum方式安装nginx 一、nginx官网 二、nginx安装 点击首页的 Docs 或者 install 都可以&#xff0c;最终都是进入到Installing nginx页面 因为安装的服务器环境是linux centos 所以选择 Installation on Linux下面 packages 跳转链接 点击packages后 最终会跳转…...

2024高级前端面试题大全

&#x1f3a8; 1、v-bind指令绑定所有属性 <comp :title"title" :color"color" /><comp v-bind"props" />&#x1f3a8; 父组件监听字组件渲染周期&#xff1a;hook:updated文章地址&#x1f3a8; Vue3 defineAsyncComponent动态导…...

[机器学习]XGBoost(3)——确定树的结构

XGBoost的目标函数详见[机器学习]XGBoost&#xff08;2&#xff09;——目标函数&#xff08;公式详解&#xff09; 确定树的结构 之前在关于目标函数的计算中&#xff0c;均假设树的结构是确定的&#xff0c;但实际上&#xff0c;当划分条件不同时&#xff0c;叶子节点包含的…...

Hutool工具包的常用工具类的使用介绍

前言 Hutool 是一个轻量级的 Java 工具类库&#xff0c;提供了非常丰富的工具方法&#xff0c;可以大大减少开发时的重复性工作。它的目标是让 Java 开发更简单、更高效。Hutool 提供了多种常用功能&#xff0c;以下是一些常用工具类的使用介绍&#xff1a; 1. StrUtil - 字符…...

ETCD备份还原

环境准备&#xff1a; master 192.168.8.128 node1 192.168.8.129 k8s版本&#xff1a; 一&#xff1a;安装etcdctl工具 1.1下载安装包&#xff1a; wget https://github.com/etcd-io/etcd/releases/download/v3.4.13/etcd-v3.4.13-linux-amd64.tar.gz 1.2解压&…...

服务器防火墙设置某个端口号只允许固定 ip地址访问

服务器防火墙设置某个端口号只允许固定 ip地址访问是运维常见的功能&#xff0c;今天我们分享一下&#xff1a; 一、Linux环境 1、firewall 方式 1&#xff09;允许特定 IP 地址访问 23 端口 sudo firewall-cmd --zonepublic --add-rich-rulerule family"ipv4" s…...

FPGA 基础了解

前言 前期一直在做关于FPGA方面的开发&#xff0c;从开始认真玩FPGA到参考原子、野火、黑金、米联客的教学资料再到参与做项目中&#xff0c;中途也参加了两个比赛整也都获得不错的成绩&#xff0c;整个阶段持续了大概快一年半的时间&#xff0c;学习了乱七八糟的知识&#xf…...

Golang学习历程【第二篇 fmt包变量、常量的定义】

Golang学习历程【第二篇 fmt包&变量、常量的定义】 1. fmt 包1.1 打印&#xff08;print&#xff09;1.1.1 Print 打印1.1.2 Println 打印后换行1.1.3 Printf 打印格式化参数 1.2 输入(Scan)1.2.1 Scan 输入1.2.2 Scanf 格式化输入 2. 变量2.1 变量的声明2.2 变量初始化&am…...

深入QML语法

文章目录 深入了解 QML 文档的结构和语法什么是 QML 文档&#xff1f;导入语句导入语句的格式示例 对象声明基本语法示例更复杂的对象声明 QML 对象类型详解1. Rectangle&#xff08;矩形&#xff09;2. Gradient&#xff08;渐变&#xff09;3. Text&#xff08;文本&#xff…...

Viggle Api上线V3-beta模型,圣诞节跳舞视频来临

历史文章 Suno AI API接入 - 将AI音乐接入到自己的产品中&#xff0c;支持120并发任务 万物皆能舞&#xff0c;AI让你秒变“舞”林高手 – Viggle AI“舞”所不能 Viggle AI&#xff1a;打造爆款 AI 视频&#xff0c;让照片 “踢” 起足球 又一款AI对口型神器&#xff0c;让…...

前端excel的实现方案Luckysheet

一、介绍 Luckysheet是一款纯前端类似excel的在线表格&#xff0c;功能强大、配置简单、完全开源的插件。目前已暂停维护&#xff0c;但是其已有功能大概能满足常见需求的使用。 二、引入 ①cdn引入&#xff08;目前应该已经不支持&#xff0c;可自行尝试&#xff09; <l…...

数据字典类型/条目表的设计目的

1.以前的设计思路 对于下拉框选项储存的思路 我们以前是直接针对每一个下拉框都关联一个表格于数据库中 这种行为很不妥当 如果对于不同业务情景下的相同下拉框来说 多个相同下拉框就会在数据库中产生多个表格 当某个下拉框的选项需要更新或者新增时 那么对应的需要同步更新相…...

abc 383 C (bfs 最短路 )D(唯一分解定理,欧拉筛)

C 题&#xff1a; 首先暴力的想&#xff0c;对于每一个加湿器的位置去 上下左右扩展是 nm 的复杂度 。最多会有 nm 个加湿器。所以复杂度到达了n^3 。肯定超时了。 我们可以发现 对于一个点 会标记很多次&#xff0c;这回导致超时。 可以采用类似 bfs 求最短路的形式&#xff…...

常用消息中间件介绍

在消息中间件这个领域&#xff0c;确实有不少专业且强大的选择&#xff0c;它们各自都有着独特的优势和适用场景。 1. Apache Kafka&#xff1a; • Kafka以其高吞吐量、低延迟和分布式架构著称&#xff0c;非常适合处理大数据量、实时性要求高的场景。 • 它支持发布/订阅模式…...

vue基础

1.v-text,v-html <!-- v-text,v-html都可以显示内容 ,v-html可以解析html标签--> <p>{{msg}}</p> <p v-text"msg"></p> <p v-html"msg"></p> <script> let appnew Vue({ el:"#max", data:{ ms…...

从Windows远程访问Linux上的数据库

从Windows远程访问Linux上的数据库 目录 简介在Linux上安装MySQL/MariaDB配置MySQL/MariaDB以允许远程连接 修改MySQL/MariaDB配置文件重启MySQL/MariaDB服务确保防火墙允许MySQL/MariaDB端口 创建远程访问用户授予用户权限测试远程连接 检查网络连通性使用图形化工具连接 创…...