# 苏州教育E卡通数据安全运维操作手册

## 前言

本手册基于苏州教育E卡通平台的实际运维需求，旨在建立一套**实用、可操作**的数据安全管控体系。聚焦于解决实际工作中真正存在的风险问题。

本手册适用于所有参与平台运维、管理的人员，包括但不限于系统管理员、客服人员、学校管理人员等。

## 一、风险分级体系

### 1.1 三级操作分类

**等保三级依据**：根据GB/T 22239-2019要求，对不同风险的操作采取相应控制措施。

#### 🔴 **关键操作** (CRITICAL)
**识别标准**：
- 系统核心配置修改
- 用户权限分配
- 审计规则修改
- 批量数据处理（≥50条）
- 系统运维重大调整
**管控要求**：
- **主管审批**：事前纸质（电子档）审批流程
- **双人确认**：一人操作，一人监督
- **双因素认证**：密码+动态码，堡垒机或摄像记录
- **操作记录**：详细日志记录
- **自动备份**：执行前自动备份

#### 🟡 **重要操作** (IMPORTANT)
**识别标准**：
- 特殊敏感数据修改（身份证、家庭住址、监护人联系方式）
- 新生录入、注册报到等
- 账号创建和权限分配（非管理员，如班主任等）

**管控要求**：
- **主管审批**：事后审核
- **双因素认证**：重要操作时启用
- **操作确认**：关键步骤二次确认
- **操作日志**：完整记录操作链路

#### 🟢 **一般操作** (NORMAL)
**识别标准**：
- 学生信息查询
- 系统状态查看
- 非敏感信息修改
- 补换卡订单处理
- 报表生成和统计

**管控要求**：
- **基本认证**：用户名密码认证
- **操作记录**：基础日志记录
- **访问控制**：基于角色的权限控制
- **会话管理**：超时自动退出

---

## 二、简化的角色体系

### 2.1 核心角色定义

| 角色 | 主要职责 | 可操作范围 | 禁止操作 |
|------|----------|------------|----------|
| **家长用户** | 查看自己孩子信息 | ✓ 查看基本信息<br>✓ 修改联系方式<br>✓ 查看卡状态 | ✗ 查看其他学生<br>✗ 修改关键信息<br>✗ 批量操作 |
| **学校教师** | 管理本校学生 | ✓ 新生录入<br>✓ 修改非关键信息<br>✓ 本校数据查询 | ✗ 跨校查询<br>✗ 删除记录<br>✗ 批量导出 |
| **客服人员** | 处理补卡业务 | ✓ 学生信息查询（补卡用）<br>✓ 处理补换卡订单<br>✓ 查询卡状态 | ✗ 查看敏感信息<br>✗ 修改数据<br>✗ 批量导出 |
| **系统（区域）管理员** | 处理学校业务 | ✓ 信息修改<br>✓ 敏感信息<br>✓ 执行任务<br>✓ 用户账号管理 | ✗ 参与业务审批<br>✗ 单独操作 |
| **审核管理员** | 业务审核 | ✓ 业务审批<br>✓ 信息查询<br>  | ✗ 修改数据<br>✗ 用户账号管理<br>✗ 单独操作 |
| **安全审计管理员** | 安全审计 | ✓ 查看所有日志<br>✓ 生成安全报告<br>✓ 设置监控规则<br>✓ 调查安全事件 | ✗ 修改业务数据<br>✗ 执行业务操作<br>✗ 查看敏感信息 |
| **系统运维人员** | 系统运维 | ✓ 服务器维护<br>✓ 数据库备份<br>✓ 执行审批脚本<br> | ✗ 查看业务数据<br>✗ 参与业务审批<br>✗ 单独操作 |

### 2.2 权限分离原则

**核心原则**：
- **操作与审核分离**：操作人不能同时是审核人
- **技术与业务分离**：系统管理员不接触业务数据
- **监督与执行分离**：安全管理员只监督不执行

**简化的权限矩阵**：

| 操作类型 | 学校教师 | 客服人员 | 系统管理员 | 安全管理员 |
|----------|----------|----------|------------|------------|
| 数据查询 | ✅(本校) | ✅(授权) | ❌ | ✅(审计) |
| 数据修改 | ✅(非关键) | ❌ | ✅(脚本) | ❌ |
| 关键操作 | ❌ | ❌ | ✅(双人) | ❌ |
| 系统运维 | ❌ | ❌ | ✅ | ❌ |
| 安全审计 | ❌ | ❌ | ❌ | ✅ |

---

## 三、统一的操作流程

### 3.1 标准三阶段流程

**所有操作统一采用三阶段流程**：

```
申请阶段 → 审批阶段 → 执行阶段
```

#### **第一阶段：申请**
- 操作人提交申请
- 系统自动检查权限
- 生成操作编号

#### **第二阶段：审批**
- **关键操作**：需要双人确认
- **重要操作**：需要主管审批
- **一般操作**：自动审批

#### **第三阶段：执行**
- 验证审批状态
- 执行操作
- 记录结果

### 3.2 操作流程简化图

```
┌─────────┐    ┌─────────┐    ┌─────────┐
│  申请   │───→│  审批   │───→│  执行   │
└─────────┘    └─────────┘    └─────────┘
     │              │              │
     │              │              │
   自动检查        分级审批        结果记录
   权限验证        双人确认        日志保存
```

---

## 四、权限控制

### 4.1 访问控制

**角色权限控制**：

```sql
-- 角色表
create table SYS_ROLE
(
  role_id     NUMBER not null,--角色主键
  role_name   VARCHAR2(30) not null,--角色名称
  role_key    VARCHAR2(100) not null,
  role_sort   NUMBER not null,
  data_scope  CHAR(1) default '1',
  status      CHAR(1) not null, --角色状态
  del_flag    CHAR(1) default '0',
  create_by   VARCHAR2(64) default '',
  create_time DATE,
  update_by   VARCHAR2(64) default '',
  update_time DATE,
  remark      VARCHAR2(500)
)

--角色菜单表
create table SYS_ROLE_MENU
(
  role_id NUMBER not null,
  menu_id NUMBER not null
)

```

### 4.2 身份鉴别

**登录认证流程**：

1. 收集身份凭证：用户名和密码

2. 创建认证令牌：UsernamePasswordToken

3. 提交认证：subject.login(token)

4. Realm 验证：自定义 Realm 中验证用户信息

5. 处理结果：成功跳转首页，失败返回错误信息

**会话管理**：
- 超时时间：30分钟超时

**会话控制**：
- 并发控制：限制同一用户最大会话数
- 踢出策略：新登录踢出旧会话或阻止新登录

### 4.3 审计日志

**审计日志结构**：

```sql
-- 审计日志
create table SYS_OPER_LOG
(
  oper_id       NUMBER not null,
  title         VARCHAR2(50) , -- 业务标题
  business_type NUMBER default 0,
  method        VARCHAR2(100), -- 方法名称
  operator_type NUMBER default 0, --操作类别（0其它 1后台用户 2手机端用户）
  oper_name     VARCHAR2(50), --操作人员
  dept_name     VARCHAR2(50),--部门名称
  oper_url      VARCHAR2(255),
  oper_ip       VARCHAR2(50),--主机地址
  oper_location VARCHAR2(255),
  oper_param    VARCHAR2(4000),
  status        NUMBER default 0,
  error_msg     VARCHAR2(4000),
  oper_time     DATE--操作时间
);
```

---

## 五、监控和告警

### 5.1 告警规则

**告警规则**：
- 连续5次登录失败
- 未审批就执行的操作

**告警处理**：
1. 系统自动发送告警
2. 安全管理员15分钟内响应
3. 记录处理结果

### 5.2 监控指标

**核心监控指标**：
- 登录成功率
- 操作执行成功率
- 异常操作数量
- 系统响应时间

---

## 六、数据备份



### 6.1 备份策略

**简单的备份方案**：
- **实时备份**：关键数据实时同步 使用oracle ram 回闪备份技术进行实时备份
- **每日备份**：全量数据备份     每日凌晨 导出 一份 dmp 文件
- **异地备份**：备份到异地存储    备份文件同步到异地存储保存
- **保留期限**：在线30天，离线1年



**磁盘监控脚本**：
每5分钟 检查一遍磁盘空间 当发现磁盘可用空间小于阈值后 发送企微告警
```
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net"
    "net/http"
    "os/exec"
    "strconv"
    "strings"
    "time"
)

// Config 配置结构体
type Config struct {
    WebhookURL     string  `json:"webhook_url"`
    UsageThreshold float64 `json:"usage_threshold"`
    Interval       int     `json:"interval"` // 新增：监控间隔时间（分钟）
}

// 获取主机的 IP 地址
func getHostIP() (string, error) {
    addrs, err := net.InterfaceAddrs()
    if err != nil {
        return "", err
    }
    for _, addr := range addrs {
        if ipnet, ok := addr.(*net.IPNet); ok &&!ipnet.IP.IsLoopback() {
            if ipnet.IP.To4() != nil {
                return ipnet.IP.String(), nil
            }
        }
    }
    return "", fmt.Errorf("未找到有效的 IP 地址")
}

// 发送消息到企业微信机器人
func sendMessage(webhookURL, message string) error {
    payload := map[string]interface{}{
        "msgtype": "text",
        "text": map[string]string{
            "content": message,
        },
    }
    payloadBytes, err := json.Marshal(payload)
    if err != nil {
        return err
    }

    resp, err := http.Post(webhookURL, "application/json", bytes.NewBuffer(payloadBytes))
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        return fmt.Errorf("发送消息失败，状态码: %d", resp.StatusCode)
    }
    return nil
}

// 获取所有挂载点的磁盘使用率
func getAllDiskUsage() (map[string]float64, error) {
    cmd := exec.Command("df")
    output, err := cmd.Output()
    if err != nil {
        return nil, err
    }

    lines := strings.Split(string(output), "\n")
    if len(lines) < 2 {
        return nil, fmt.Errorf("未找到磁盘使用信息")
    }

    usageMap := make(map[string]float64)
    for _, line := range lines[1:] {
        if line == "" {
            continue
        }
        fields := strings.Fields(line)
        if len(fields) < 6 {
            continue
        }
        mountPoint := fields[5]
        usageStr := strings.TrimRight(fields[4], "%")
        usage, err := strconv.ParseFloat(usageStr, 64)
        if err != nil {
            continue
        }
        usageMap[mountPoint] = usage
    }
    return usageMap, nil
}

func monitorDiskUsage(config Config) {
    ip, err := getHostIP()
    if err != nil {
        log.Printf("获取 IP 地址失败: %v", err)
        ip = "未知 IP"
    }

    usageMap, err := getAllDiskUsage()
    if err != nil {
        log.Fatalf("获取磁盘使用率失败: %v", err)
    }

    var alertMessages []string
    for mountPoint, usage := range usageMap {
        if usage > config.UsageThreshold {
            message := fmt.Sprintf("警告：IP 地址为 %s 的主机，挂载点 %s 的磁盘使用率已达到 %.2f%%，超过阈值 %.2f%%！", ip, mountPoint, usage, config.UsageThreshold)
            alertMessages = append(alertMessages, message)
        }
    }

    if len(alertMessages) > 0 {
        combinedMessage := strings.Join(alertMessages, "\n")
        err := sendMessage(config.WebhookURL, combinedMessage)
        if err != nil {
            log.Printf("发送告警消息失败: %v", err)
        } else {
            log.Printf("已发送告警消息: %s", combinedMessage)
        }
    } else {
        log.Println("所有挂载点的磁盘使用率正常")
    }
}

func main() {
    // 读取配置文件
    configData, err := ioutil.ReadFile("config.json")
    if err != nil {
        log.Fatalf("读取配置文件失败: %v", err)
    }
    var config Config
    err = json.Unmarshal(configData, &config)
    if err != nil {
        log.Fatalf("解析配置文件失败: %v", err)
    }

    // 首次执行监控
    monitorDiskUsage(config)

    // 创建定时器
    ticker := time.NewTicker(time.Duration(config.Interval) * time.Minute)
    defer ticker.Stop()

    for range ticker.C {
        monitorDiskUsage(config)
    }
}

```
---

## 七、应急响应

### 7.1 简化的应急流程

**三级响应**：

| 事件级别 | 响应时间 | 处理方式 |
|----------|----------|----------|
| **一般事件** | 2小时内 | 在线处理 |
| **重要事件** | 30分钟内 | 紧急处理 |
| **重大事件** | 15分钟内 | 立即处理 |

### 7.2 应急联系人

| 角色 | 联系人 | 电话 |
|------|--------|------|
| 应急总指挥 | [姓名] | [电话] |
| 技术负责人 | [姓名] | [电话] |
| 安全负责人 | [姓名] | [电话] |

---

## 八、培训和考核

### 8.1 培训内容

**新员工培训**（4小时）：
- 手册内容和操作规范（2小时）
- 系统操作演示（1小时）
- 应急流程说明（1小时）

**年度复训**（2小时）：
- 安全事件案例分析（1小时）
- 操作规范更新（1小时）

### 8.2 考核要求

- 每年1次操作规范考试
- 每半年1次应急演练
- 不合格人员重新培训

---

## 九、操作检查表

### 9.1 关键操作检查表

**申请阶段**：
- [ ] 操作目的明确
- [ ] 影响范围确认
- [ ] 申请人权限验证

**审批阶段**：
- [ ] 必要性评估
- [ ] 风险评估
- [ ] 备份方案确认

**执行阶段**：
- [ ] 双人确认（关键操作）
- [ ] 操作步骤按计划执行
- [ ] 结果验证

**完成阶段**：
- [ ] 操作记录保存
- [ ] 相关人员通知
- [ ] 异常情况处理

### 9.2 系统管理员操作检查表

**操作前**：
- [ ] 维护时间窗口确认
- [ ] 影响范围评估
- [ ] 备份完成确认
- [ ] 回滚方案准备

**操作中**：
- [ ] 按计划执行
- [ ] 每步确认结果
- [ ] 异常情况记录

**操作后**：
- [ ] 系统功能验证
- [ ] 性能检查
- [ ] 操作记录归档

---

## 十、附录

### 附录A：角色申请表

```
申请编号: [自动生成]
申请人: [姓名]
所属部门: [部门]
申请角色: [角色名称]
申请原因: [详细说明]

申请权限:
□ 查询权限
□ 修改权限
□ 删除权限
□ 系统管理权限

申请人签字: _________ 日期: _________
部门主管审批: _________ 日期: _________
安全管理员审核: _________ 日期: _________
```

### 附录B：操作申请单

```
申请单编号: [自动生成]
申请时间: YYYY-MM-DD HH:MM
申请人: [姓名]
操作类型: [关键/重要/一般]
操作描述: [详细说明]

影响范围: [影响的人数/系统范围]
操作步骤: [简要步骤]

申请人签字: _________ 日期: _________
审批人签字: _________ 日期: _________
执行确认: _________ 日期: _________
```

### 附录C：应急响应记录表

```
事件编号: [自动生成]
发生时间: YYYY-MM-DD HH:MM
事件类型: [一般/重要/重大]
事件描述: [简要描述]

响应时间: ____分钟
处理过程: [简要记录]
处理结果: [成功/失败]

处理人签字: _________ 日期: _________
确认人签字: _________ 日期: _________
```

---

## 结语

**简单就是美**

本手册采用**简化的设计**，在满足等保三级要求的同时，最大限度地降低系统复杂度和操作难度。

**核心原则**：
- 消除特殊情况
- 统一操作流程
- 减少概念数量
- 保持实用主义

通过这种方式，我们既能满足合规要求，又能确保系统的可维护性和操作的便利性。

---

**本手册自发布之日起执行，由数据安全管理领导小组负责解释和修订。**