主数据安全的特殊性:核心资产的多维防护
主数据(Master Data)作为企业最核心的数据资产,承载着组织、客户、供应商、物料等基础业务实体信息。与普通业务数据不同,主数据具有三个显著特征,使其安全防护面临独特挑战:
核心资产属性:主数据是企业运营的基石,一旦泄露或篡改,将直接影响多个业务系统的正常运行。客户信息泄露可能导致合规风险,供应商数据被篡改可能引发供应链危机。
多系统共享:主数据通常被ERP、CRM、SRM、财务系统等10+个下游系统消费。每个系统的访问模式、权限需求、安全等级各不相同,权限管理的复杂度呈指数级增长。
权限复杂度:同一个客户数据,销售部门需要查看完整联系方式,财务部门只需要发票信息,客服部门需要历史交互记录。数据行级、字段级的细粒度权限控制成为刚需。
基于这些特性,主数据管理平台(MDM)的安全设计不能简单套用传统Web应用的安全方案,而需要构建一套覆盖数据层、接口层、审计层的全栈安全体系。
安全架构三层模型
主数据管理平台的安全架构采用分层设计,将安全能力解耦为三个独立但协同的层次。这种分层设计的核心思想是纵深防御(Defense in Depth),即使某一层的安全措施被突破,其他层仍能提供保护。每一层都聚焦于特定的安全领域,通过标准化接口与上下层交互,既保证了安全能力的专业性,又降低了系统整体的复杂度。
在设计安全架构时,需要遵循几个关键原则:最小权限原则(用户只能获得完成工作所必需的最小权限集合)、职责分离原则(关键操作需要多人协作完成,防止单人滥用权限)、可审计原则(所有安全相关行为都必须被完整记录)、默认拒绝原则(未明确授权的操作一律禁止)。这些原则贯穿于三层架构的每一个组件设计中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
┌─────────────────────────────────────────────────────────┐
│ 审计层安全 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 操作日志 │ │ 数据变更 │ │ 访问审计 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────┘
↓↑
┌─────────────────────────────────────────────────────────┐
│ 接口层安全 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 接口鉴权 │ │ 流量控制 │ │ 防重放 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────┘
↓↑
┌─────────────────────────────────────────────────────────┐
│ 数据层安全 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 数据脱敏 │ │ 权限隔离 │ │ 加密存储 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────┘
|
数据层安全负责数据的静态保护和访问控制,包括数据脱敏、权限隔离、加密存储等核心能力。这一层的安全机制直接作用于数据存储和查询阶段。
接口层安全负责API调用的身份认证和流量控制,确保只有合法的系统调用能够访问主数据。接口鉴权、限流、防重放攻击是这一层的核心能力。
审计层安全负责记录所有数据访问和变更行为,为安全事件追溯和合规审计提供证据。操作日志、数据变更审计、访问审计构成完整的审计链条。
数据脱敏设计
数据脱敏是主数据安全的最后一道防线。即使权限控制失效,脱敏也能确保敏感数据不以明文形式暴露。在实际工程中,主数据平台通常需要同时支持静态脱敏和动态脱敏两种模式,并根据业务场景灵活切换。脱敏的核心原则是:在保证数据可用性的前提下,最大限度降低敏感信息暴露风险。
数据生命周期安全策略要求在每个阶段采取不同的脱敏策略。数据创建阶段执行分类标记,识别敏感字段并赋予安全等级;数据存储阶段采用加密保护;数据使用阶段通过动态脱敏控制可见性;数据共享阶段通过静态脱敏生成安全副本;数据销毁阶段执行物理擦除并记录审计日志。
静态脱敏 vs 动态脱敏
静态脱敏在数据导出或同步时执行,将原始数据永久替换为脱敏后的数据。适用于测试环境数据准备、数据归档等场景。
1
2
3
4
5
6
7
8
|
-- 静态脱敏示例:客户手机号脱敏
UPDATE mdm_customer
SET phone = CONCAT(
SUBSTRING(phone, 1, 3),
'****',
SUBSTRING(phone, 8, 4)
)
WHERE export_target = 'TEST_ENV';
|
动态脱敏在数据查询时实时执行,根据访问者身份动态决定是否脱敏以及脱敏粒度。原始数据保持不变,适用于生产环境的细粒度访问控制。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// 动态脱敏拦截器
@Component
public class DataMaskingInterceptor implements HandlerInterceptor {
@Autowired
private MaskingRuleEngine ruleEngine;
@Override
public void postProcess(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) {
if (modelAndView != null && modelAndView.getModel() != null) {
Object data = modelAndView.getModel().get("data");
UserContext user = SecurityContextHolder.getCurrentUser();
// 根据用户角色和字段敏感级别动态脱敏
ruleEngine.applyMasking(data, user);
}
}
}
|
脱敏规则引擎
脱敏规则引擎采用声明式配置,将脱敏策略与业务代码解耦。规则定义包含四个维度:目标字段、脱敏算法、适用角色、优先级。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
# 脱敏规则配置
masking_rules:
- field: customer.phone
algorithm: phone_mask
apply_to:
- role: SALES
mask: false
- role: FINANCE
mask: true
pattern: "***-****-{last4}"
- role: SUPPORT
mask: true
pattern: "{first3}****"
priority: 100
- field: customer.id_card
algorithm: id_card_mask
apply_to:
- role: "*"
mask: true
pattern: "{first6}********{last4}"
priority: 200
- field: supplier.bank_account
algorithm: bank_mask
apply_to:
- role: FINANCE
mask: false
- role: "*"
mask: true
pattern: "****{last4}"
priority: 150
|
字段级脱敏策略
主数据平台支持多种脱敏算法,针对不同类型的敏感数据:
| 数据类型 |
脱敏算法 |
示例(原始→脱敏) |
适用场景 |
| 手机号 |
保留前3后4 |
13812345678→138****5678 |
客户联系信息 |
| 身份证号 |
保留前6后4 |
110101199001011234→110101********1234 |
个人身份信息 |
| 银行卡号 |
保留后4位 |
6222001234567890→************7890 |
财务支付信息 |
| 邮箱地址 |
保留域名 |
user@example.com→u***@example.com |
电子联系方式 |
| 姓名 |
保留姓氏 |
张三→张* |
个人身份信息 |
| 地址 |
保留省市 |
北京市朝阳区XX路→北京市*** |
位置信息 |
脱敏算法的实现需要考虑数据可用性。过度脱敏会导致数据失去业务价值,脱敏不足则无法保护隐私。规则引擎支持自定义脱敏函数,允许业务方根据具体需求定义脱敏策略。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
// 自定义脱敏算法示例
public class CustomMaskingAlgorithm implements MaskingStrategy {
@Override
public String mask(String original, MaskingContext context) {
if (original == null || original.length() < 4) {
return "***";
}
// 根据上下文动态决定脱敏粒度
String role = context.getUserRole();
if ("ADMIN".equals(role)) {
return original; // 管理员查看完整数据
}
int preserveLength = context.getConfig().getPreserveLength();
int totalLength = original.length();
StringBuilder masked = new StringBuilder();
masked.append(original.substring(0, preserveLength));
for (int i = preserveLength; i < totalLength - preserveLength; i++) {
masked.append("*");
}
masked.append(original.substring(totalLength - preserveLength));
return masked.toString();
}
}
|
权限隔离体系
主数据平台的权限隔离是整个安全体系中最复杂的部分。与普通业务系统不同,主数据平台需要同时满足多维度、多层次的访问控制需求:不同部门对同一数据实体的访问权限不同,同一用户在不同场景下需要的权限不同,不同组织之间的数据需要严格隔离。
权限体系的设计需要平衡安全性和易用性。过于严格的权限控制会影响业务效率,过于宽松的控制则带来安全风险。实践中通常采用"默认最小权限 + 按需申请"的模式,新员工入职时只获得基础查看权限,随着业务需要逐步申请更高级别的权限。
主数据平台的权限隔离采用RBAC(基于角色的访问控制)与ABAC(基于属性的访问控制)混合模型,在保证管理简洁性的同时实现细粒度控制。
RBAC+ABAC混合模型
RBAC负责粗粒度的功能权限控制,定义"谁能做什么"。ABAC负责细粒度的数据权限控制,定义"谁能看到哪些数据"。
1
2
3
4
5
6
7
8
9
10
11
|
┌─────────────────────────────────────────┐
│ RBAC 功能权限层 │
│ 用户 → 角色 → 权限(菜单、按钮、接口) │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ ABAC 数据权限层 │
│ 用户属性 + 数据属性 + 环境属性 → 决策 │
│ (部门=销售) + (客户.所属区域=华东) │
│ + (时间=工作日) → 允许访问 │
└─────────────────────────────────────────┘
|
RBAC权限定义:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
-- 角色定义
CREATE TABLE sys_role (
role_id VARCHAR(32) PRIMARY KEY,
role_name VARCHAR(64) NOT NULL,
role_code VARCHAR(32) UNIQUE NOT NULL,
data_scope TINYINT COMMENT '1:全部 2:本部门 3:本部门及下级 4:自定义 5:仅本人'
);
-- 角色权限关联
CREATE TABLE sys_role_permission (
role_id VARCHAR(32),
permission_id VARCHAR(32),
PRIMARY KEY (role_id, permission_id)
);
-- 用户角色关联
CREATE TABLE sys_user_role (
user_id VARCHAR(32),
role_id VARCHAR(32),
PRIMARY KEY (user_id, role_id)
);
|
ABAC策略定义:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
// ABAC策略引擎
@Service
public class DataAccessPolicyEngine {
public boolean evaluate(UserContext user, DataRecord record, String action) {
// 策略1:部门数据隔离
if (user.getDepartment() != null && record.getOwnerDept() != null) {
if (!isDeptAccessible(user.getDepartment(), record.getOwnerDept())) {
return false;
}
}
// 策略2:数据密级控制
if (record.getSecurityLevel() != null) {
if (user.getClearanceLevel() < record.getSecurityLevel()) {
return false;
}
}
// 策略3:时间窗口控制
LocalTime now = LocalTime.now();
if (!isWithinWorkHours(now) && user.getRole().equals("NORMAL_USER")) {
return false;
}
return true;
}
private boolean isDeptAccessible(String userDept, String dataDept) {
// 判断用户部门是否能访问数据所属部门的数据
// 支持部门层级关系:本部门、本部门及下级部门、自定义部门列表
DepartmentHierarchy hierarchy = departmentService.getHierarchy();
return hierarchy.isAccessible(userDept, dataDept);
}
}
|
数据行级权限
行级权限控制用户能看到哪些数据行。主数据平台支持四种行级权限模式:
全部数据:用户可以查看所有数据,适用于系统管理员、数据治理专员。
本部门数据:用户只能查看本部门创建或负责的数据,适用于部门数据专员。
本部门及下级部门:用户可查看本部门及所有下级部门的数据,适用于部门管理者。
自定义数据范围:通过规则定义个性化的数据访问范围,适用于跨部门协作场景。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
-- 数据权限过滤器(MyBatis拦截器实现)
<if test="dataScope == '2'">
AND owner_dept_id = #{userDeptId}
</if>
<if test="dataScope == '3'">
AND owner_dept_id IN (
SELECT dept_id FROM sys_dept
WHERE dept_path LIKE CONCAT(#{userDeptPath}, '%')
)
</if>
<if test="dataScope == '4'">
AND owner_dept_id IN (
SELECT dept_id FROM sys_role_dept
WHERE role_id = #{roleId}
)
</if>
|
跨组织权限隔离
在集团化企业场景下,主数据平台需要支持多组织架构,确保不同法人实体之间的数据隔离。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
# 多组织架构配置
organizations:
- org_id: "ORG001"
org_name: "东风汽车集团"
org_type: "GROUP"
children:
- org_id: "ORG001-01"
org_name: "东风乘用车"
org_type: "SUBSIDIARY"
data_isolation: true
- org_id: "ORG001-02"
org_name: "东风商用车"
org_type: "SUBSIDIARY"
data_isolation: true
# 数据隔离规则
isolation_rules:
- rule_id: "R001"
description: "子公司数据完全隔离"
apply_to: ["ORG001-01", "ORG001-02"]
policy: "STRICT"
- rule_id: "R002"
description: "集团可查看子公司汇总数据"
apply_to: ["ORG001"]
policy: "AGGREGATE_ONLY"
visible_fields: ["org_id", "data_count", "summary_metrics"]
|
审计追溯全栈设计
审计追溯是主数据安全的"黑匣子",记录所有数据访问和变更行为,为安全事件调查和合规审计提供完整证据链。
操作日志
操作日志记录用户在平台上的所有操作行为,包括登录、查询、导出、配置变更等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
// 操作日志切面
@Aspect
@Component
public class OperationLogAspect {
@Around("@annotation(operationLog)")
public Object around(ProceedingJoinPoint point, OperationLog operationLog) throws Throwable {
long startTime = System.currentTimeMillis();
// 记录操作前状态
OperationRecord record = new OperationRecord();
record.setUserId(SecurityContextHolder.getUserId());
record.setOperation(operationLog.value());
record.setModule(operationLog.module());
record.setIp(getClientIp());
record.setStartTime(new Date());
Object result = null;
boolean success = false;
try {
result = point.proceed();
success = true;
return result;
} finally {
// 记录操作后状态
record.setDuration(System.currentTimeMillis() - startTime);
record.setSuccess(success);
record.setParams(getMethodParams(point));
record.setResult(success ? "SUCCESS" : "FAILED");
// 异步写入日志
logService.asyncSave(record);
}
}
}
|
数据变更审计
数据变更审计记录主数据的每一次创建、修改、删除操作,包括变更前后的完整数据快照。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
-- 数据变更审计表
CREATE TABLE mdm_data_audit (
audit_id BIGINT PRIMARY KEY AUTO_INCREMENT,
entity_type VARCHAR(64) NOT NULL COMMENT '实体类型:customer/supplier/material',
entity_id VARCHAR(64) NOT NULL COMMENT '实体ID',
operation_type VARCHAR(16) NOT NULL COMMENT 'CREATE/UPDATE/DELETE',
before_data JSON COMMENT '变更前数据快照',
after_data JSON COMMENT '变更后数据快照',
changed_fields JSON COMMENT '变更字段列表',
operator_id VARCHAR(32) NOT NULL,
operator_name VARCHAR(64),
operate_time DATETIME NOT NULL,
source_system VARCHAR(64) COMMENT '来源系统',
INDEX idx_entity (entity_type, entity_id),
INDEX idx_time (operate_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
变更审计的关键是记录"谁在什么时间把什么数据从什么值改成了什么值"。通过对比before_data和after_data,可以精确还原每一次数据变更的完整上下文。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
// 数据变更监听器
@Component
public class DataChangeAuditor {
@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
public void handleDataChange(DataChangeEvent event) {
DataAuditRecord record = new DataAuditRecord();
record.setEntityType(event.getEntityType());
record.setEntityId(event.getEntityId());
record.setOperationType(event.getType());
// 捕获变更前数据
if (event.getType() != OperationType.CREATE) {
record.setBeforeData(
entityRepository.findSnapshot(event.getEntityId())
);
}
// 捕获变更后数据
if (event.getType() != OperationType.DELETE) {
record.setAfterData(event.getNewData());
}
// 计算变更字段
record.setChangedFields(
calculateChangedFields(record.getBeforeData(), record.getAfterData())
);
// 记录操作人信息
UserContext user = SecurityContextHolder.getCurrentUser();
record.setOperatorId(user.getUserId());
record.setOperatorName(user.getUserName());
record.setOperateTime(new Date());
auditRepository.save(record);
}
}
|
访问审计
访问审计记录每一次数据查询行为,包括查询条件、返回数据量、访问时长等。这对于发现异常访问模式(如批量导出、频繁查询敏感字段)至关重要。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
{
"access_id": "ACC20260706001",
"user_id": "user_12345",
"user_name": "张三",
"access_time": "2026-07-06T10:30:45.123+08:00",
"entity_type": "customer",
"query_condition": {
"region": "华东",
"status": "ACTIVE",
"created_after": "2026-01-01"
},
"result_count": 1250,
"accessed_fields": ["customer_id", "customer_name", "phone", "address"],
"sensitive_fields_accessed": ["phone"],
"duration_ms": 342,
"source_ip": "192.168.1.100",
"source_system": "CRM",
"risk_level": "NORMAL"
}
|
合规报表
基于审计数据,平台自动生成各类合规报表,满足等保2.0、个人信息保护法等法规要求:
| 报表类型 |
统计维度 |
更新频率 |
用途 |
| 数据访问统计 |
按用户/部门/时间 |
每日 |
发现异常访问模式 |
| 敏感数据访问 |
按字段/用户/时间 |
实时 |
监控敏感数据访问 |
| 权限变更记录 |
按角色/用户/时间 |
实时 |
权限审计追溯 |
| 数据导出统计 |
按用户/数据类型/数量 |
每日 |
防止数据泄露 |
| 异常操作告警 |
按风险等级/类型 |
实时 |
安全事件响应 |
安全编码实践
安全编码是防止主数据平台遭受攻击的基础防线。以下是关键的安全编码实践:
防SQL注入
SQL注入是数据库应用最常见的攻击方式。主数据平台采用参数化查询和ORM框架双重防护:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// ❌ 错误示例:字符串拼接(存在SQL注入风险)
String sql = "SELECT * FROM mdm_customer WHERE customer_name = '" + name + "'";
// ✅ 正确示例:参数化查询
String sql = "SELECT * FROM mdm_customer WHERE customer_name = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, name);
ResultSet rs = pstmt.executeQuery();
// ✅ 正确示例:MyBatis参数绑定
<select id="selectCustomer">
SELECT * FROM mdm_customer
WHERE customer_name = #{name}
AND status = #{status}
</select>
|
对于动态SQL拼接场景,必须使用白名单校验:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// 动态排序字段白名单
private static final Set<String> ALLOWED_SORT_FIELDS = Set.of(
"customer_id", "customer_name", "created_time", "status"
);
public String buildOrderBy(String sortField, String sortOrder) {
if (!ALLOWED_SORT_FIELDS.contains(sortField)) {
throw new IllegalArgumentException("Invalid sort field: " + sortField);
}
String order = "ASC".equalsIgnoreCase(sortOrder) ? "ASC" : "DESC";
return " ORDER BY " + sortField + " " + order;
}
|
防XSS攻击
XSS(跨站脚本攻击)通过注入恶意脚本窃取用户信息。防护措施包括输入过滤和输出编码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
// XSS过滤器
@Component
public class XssFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
XssHttpServletRequestWrapper wrappedRequest =
new XssHttpServletRequestWrapper(httpRequest);
chain.doFilter(wrappedRequest, response);
}
}
// 请求包装器:对输入参数进行HTML转义
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
@Override
public String getParameter(String name) {
String value = super.getParameter(name);
return value != null ? HtmlUtils.htmlEscape(value) : null;
}
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values == null) return null;
String[] escapedValues = new String[values.length];
for (int i = 0; i < values.length; i++) {
escapedValues[i] = HtmlUtils.htmlEscape(values[i]);
}
return escapedValues;
}
}
|
接口鉴权
主数据平台对外提供REST API供下游系统调用,接口鉴权采用JWT + API Key双重机制:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
// API鉴权拦截器
@Component
public class ApiAuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
// 1. 验证API Key
String apiKey = request.getHeader("X-API-Key");
if (!apiKeyService.validate(apiKey)) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return false;
}
// 2. 验证JWT Token
String token = request.getHeader("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return false;
}
try {
Claims claims = jwtService.parse(token.substring(7));
// 3. 验证权限
String requiredPermission = getRequiredPermission(handler);
if (!hasPermission(claims, requiredPermission)) {
response.setStatus(HttpStatus.FORBIDDEN.value());
return false;
}
// 4. 记录API调用
apiCallLogService.record(request, claims);
return true;
} catch (JwtException e) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return false;
}
}
}
|
安全测试与合规
渗透测试
主数据平台上线前必须通过渗透测试,验证安全防护体系的有效性。测试范围包括:
OWASP Top 10:SQL注入、XSS、CSRF、身份认证缺陷、敏感数据泄露等。
业务逻辑漏洞:越权访问、数据篡改、批量导出等。
接口安全:未授权访问、参数篡改、重放攻击等。
1
2
3
4
5
6
7
8
9
|
# 渗透测试工具示例
# SQL注入检测
sqlmap -u "http://mdm.example.com/api/customer?id=1" --batch --level=3
# XSS漏洞扫描
xsser -u "http://mdm.example.com/search" -g "q=" --auto
# 目录遍历检测
dirb http://mdm.example.com/ /usr/share/dirb/wordlists/common.txt
|
等保2.0对标
主数据平台按照等保2.0三级要求进行安全建设和测评,核心要求包括:
| 安全域 |
等保2.0要求 |
平台实现方案 |
| 身份鉴别 |
双因素认证 |
密码 + 短信验证码/动态令牌 |
| 访问控制 |
最小权限原则 |
RBAC + ABAC细粒度权限控制 |
| 安全审计 |
操作行为可追溯 |
全量操作日志 + 数据变更审计 |
| 数据完整性 |
防止数据篡改 |
数字签名 + 变更审计 |
| 数据保密性 |
敏感数据加密 |
传输加密(TLS) + 存储加密(AES) |
| 数据备份恢复 |
定期备份、可恢复 |
每日全量 + 实时增量备份 |
多数据库适配安全
主数据平台支持多种数据库(MySQL、Oracle、达梦、人大金仓),不同数据库的安全特性存在差异,需要针对性适配:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
# 数据库安全适配配置
database_security:
mysql:
version: "8.0.27+"
encryption: "TDE (Transparent Data Encryption)"
audit_plugin: "audit_log"
password_policy: "validate_password"
oracle:
version: "12c+"
encryption: "TDE + Data Redaction"
audit: "Unified Auditing"
privilege_management: "Database Vault"
dameng:
version: "7/8"
encryption: "透明加密"
audit: "审计日志"
access_control: "三权分立"
kingbase:
version: "V8R3+"
encryption: "存储加密"
audit: "安全审计"
label_security: "标记安全"
|
安全威胁矩阵
| 威胁类型 |
攻击方式 |
风险等级 |
防护措施 |
检测方式 |
| SQL注入 |
恶意SQL拼接 |
高 |
参数化查询、ORM框架 |
WAF规则、SQL审计 |
| XSS攻击 |
脚本注入 |
中 |
输入过滤、输出编码 |
前端扫描、CSP策略 |
| 越权访问 |
水平/垂直越权 |
高 |
RBAC+ABAC权限控制 |
访问审计、异常检测 |
| 数据泄露 |
批量导出、截获 |
高 |
数据脱敏、传输加密 |
导出监控、流量分析 |
| 数据篡改 |
恶意修改数据 |
高 |
数字签名、变更审计 |
数据一致性校验 |
| 重放攻击 |
重复提交请求 |
中 |
防重放机制、时间戳 |
接口日志分析 |
| 暴力破解 |
密码猜测 |
中 |
账户锁定、验证码 |
登录日志监控 |
| 内部威胁 |
员工滥用权限 |
高 |
最小权限、操作审计 |
行为分析、异常告警 |
权限模型对比
| 权限模型 |
控制粒度 |
管理复杂度 |
灵活性 |
适用场景 |
| ACL |
对象级 |
高 |
低 |
小型系统、文件权限 |
| RBAC |
功能级 |
中 |
中 |
企业应用、功能权限 |
| ABAC |
数据级 |
高 |
高 |
细粒度数据权限 |
| RBAC+ABAC |
功能+数据 |
中 |
高 |
主数据平台(推荐) |
主数据平台采用RBAC+ABAC混合模型,RBAC管理功能权限(菜单、按钮、接口),ABAC管理数据权限(行级、字段级),在保证管理效率的同时实现细粒度控制。
审计指标体系
| 指标类别 |
指标名称 |
计算方式 |
告警阈值 |
业务含义 |
| 访问频率 |
单用户小时查询次数 |
COUNT(query) / user / hour |
> 1000次 |
发现异常批量查询 |
| 数据导出 |
单次导出数据量 |
MAX(export_count) / request |
> 10000条 |
防止大规模数据泄露 |
| 敏感访问 |
敏感字段访问次数 |
COUNT(access) WHERE sensitive=true |
> 100次/天 |
监控敏感数据访问 |
| 权限变更 |
角色权限调整频率 |
COUNT(permission_change) / day |
> 10次 |
发现异常权限调整 |
| 异常登录 |
非工作时间登录 |
COUNT(login) WHERE time NOT IN work_hours |
> 0次 |
发现可疑登录行为 |
| 失败尝试 |
登录失败次数 |
COUNT(login_fail) / user / hour |
> 5次 |
防止暴力破解 |
| 数据变更 |
单记录修改次数 |
COUNT(update) / entity / day |
> 10次 |
发现异常数据篡改 |
| 跨区访问 |
跨区域数据访问 |
COUNT(access) WHERE region_mismatch |
> 0次 |
发现越权访问 |
总结
主数据管理平台的安全设计是一项系统工程,需要在数据层、接口层、审计层构建完整的防护体系。数据脱敏确保敏感数据不以明文暴露,权限隔离确保只有合法用户能访问授权数据,审计追溯确保所有行为可追溯、可问责。
安全不是一次性工程,而是持续演进的过程。随着业务发展、威胁变化、法规更新,安全策略需要不断调整和优化。建立安全运营中心(SOC),实施持续监控和响应,是主数据平台安全运营的长期保障。