欢迎光临
我们一直在努力

运维--数据资源管理

前言

 更多运维相关知识:蓝队技能学习_其实防守也摸鱼的博客-CSDN博客

持续更新ing~

本文内容介绍

本文详细介绍了在SQL Server中实现数据安全防护的完整流程,包括:

  • 数据脱敏(动态掩码)
    • 使用ALTER TABLE语句为手机号字段添加部分掩码规则(保留前3后4位)
    • 通过权限控制实现不同用户查看脱敏/明文数据
  • 数据加密(列级加密)
    • 建立三层加密体系:数据库主密钥→证书→对称密钥(AES_256)
    • 实现身份证字段的加密存储,将明文转换为二进制密文
    • 通过触发器实现自动加密,确保新数据合规
  • 权限管控
    • 创建测试用户并授予受限权限
    • 验证普通用户只能看到脱敏数据
  • 数据溯源
    • 通过查询层水印(动态添加追踪标识)
    • 存储层水印(DEFAULT约束自动标记数据来源)

    文中还特别强调了政务系统中需使用国密算法(如SM4)替代国际算法的合规要求,并对比了存储加密与展示脱敏的技术差异。所有操作均配有详细SQL代码示例和错误排查方案,形成完整的数据安全防护闭环。

    知识点

    🛡️ 数据安全案例剖析

    文档通过三个真实案例揭示了数据泄露的主要风险点:

  • 开发人员违规操作:某技术承包商将包含1.5万余条公民个人信息的政务数据置于互联网环境进行测试,因存储端存在高危漏洞导致数据泄露,并在境外黑客论坛被兜售。
    • 核心问题:测试环境与生产环境未隔离、敏感信息未脱敏加密、缺乏溯源手段。
  • 网络攻击与防护不足:某单位信息系统因防范技术措施不完善,存在监测漏洞且未及时修复,导致系统“带病”运营,重要数据被恶意篡改。
    • 核心问题:技术防护措施缺失、安全缺陷修复不及时、系统日志留存不足6个月。
  • 人员疏忽导致信息遭窃:技术人员在论坛分享经验时,不慎上传了包含明文账号密码的代码,导致上海公安数据库10亿人信息面临被窃取风险。
    • 核心问题:人员安全意识薄弱、权限核验缺失、请求参数明文传输。
  • 🛠️ 十大数据安全技术能力

    为应对上述风险,文档提出了聚焦“五不”目标的一体化数据安全技术体系,包含十大核心能力:

    能力类别核心能力主要作用
    监测类 态势感知 像安全警报系统,通过日志分析快速识别和预警安全风险。
    接口审计 像监控摄像头,记录分析接口数据访问行为,发现异常和滥用。
    工具类 分类分级 识别数据敏感性(L1-L4),为不同级别数据配置差异化的存储、访问和审计策略。
    数据加密 将数据转换成密文,确保即使数据被窃取也无法轻易解读。
    数据脱敏 隐藏或改变个人身份信息,在保留数据可用性的同时保护隐私。
    数据水印 在数据中嵌入隐形标记,一旦发生泄露可快速溯源到泄露源头。
    管控类 权限管控 严格控制数据访问权限,遵循最小化授权原则,防止未授权访问。
    数据沙箱 提供独立安全的环境供开发运维使用,对数据操作行为进行全面审计和管控。
    一、什么是“数据分类分级”?

    这是数据安全治理的核心环节,目的是:

    • 分类:按业务属性或数据类型(如个人信息、金融数据、企业数据)归类;
    • 分级:根据数据泄露后可能造成的危害程度(对个人、组织、社会、国家安全的影响),划分为不同安全等级,通常分为4级:
      • 核心数据:关系国家安全、经济运行命脉,泄露将造成特别严重危害;
      • 重要数据:影响公共利益、行业稳定或大规模人群权益;
      • 敏感一般数据:涉及个人隐私或企业商业秘密,泄露会造成中等以上损害;
      • 常规一般数据:公开或低敏感度信息,泄露影响较小。
    字段名称典型分类典型分级说明
    密码 身份鉴别信息 敏感一般数据(部分场景为重要数据) 直接关联账户安全,泄露可导致身份冒用、资金损失。
    手机号 个人通信标识 敏感一般数据 可用于精准诈骗、骚扰、社工攻击,常与身份证号、地址组合使用。
    地址、固定电话、手机号 个人位置与联系方式 敏感一般数据 组合后可构建完整个人画像,用于线下骚扰或精准营销。
    统一社会信用代码 企业唯一标识 敏感一般数据(部分场景为重要数据) 可用于企业冒名注册、税务欺诈、供应链攻击。
    身份证号码 个人法定身份标识 敏感一般数据(高敏感) 黑灰产中威胁等级最高,常用于“开盒”、贷款诈骗、身份盗用。
    未成年人身份证号 特殊群体身份信息 敏感一般数据(高敏感) 法律重点保护对象,泄露后果更严重,可能触发监管处罚。
    车牌号 个人财产与行踪标识 敏感一般数据 可关联车主身份、行驶轨迹,用于跟踪、勒索或车辆盗抢。
    银行卡号 金融账户标识 敏感一般数据(高敏感) 与密码、CVV组合可直接盗刷资金,是黑灰产核心目标。
    电子邮箱 网络身份标识 敏感一般数据 常用于钓鱼、撞库、重置密码,是攻击入口之一。
    姓名 + 手机号 + 身份证 个人身份三要素 敏感一般数据(高敏感) 三者组合可完成绝大多数实名认证,是“精准诈骗”的基础。
    级别定义典型字段示例
    L1(常规一般数据) 泄露后不会对个人权益、组织权益造成危害,多为公开或脱敏数据。 产品名称、公开地址、非敏感业务描述
    L2(低敏感一般数据) 泄露后可能造成轻微影响,如骚扰电话、营销干扰。 手机号(单独)、电子邮箱、固定电话
    L3(敏感一般数据) 泄露后可能导致身份盗用、资金损失、精准诈骗等中等以上损害。 身份证号、银行卡号、密码、车牌号、未成年人信息、统一社会信用代码
    L4(重要/核心数据) 泄露后可能引发大规模社会风险、行业动荡或国家安全威胁。 国家人口库、金融交易流水、生物识别原始数据、关键基础设施配置
    • 密码 → L3(高敏感),部分金融系统视为L4;
    • 手机号 → L2(单独存在时),若与身份证、地址组合则升级为L3;
    • 地址 + 固定电话 + 手机号 → L3(组合后可构建完整画像);
    • 统一社会信用代码 → L3(企业级敏感数据,部分场景为L4);
    • 身份证号码 → L3(高敏感),未成年人身份证号同样为L3,但法律要求更严格;
    • 车牌号 → L3(可关联行踪与财产);
    • 银行卡号 → L3(高敏感),与CVV、密码组合即为L4;
    • 姓名 + 手机号 + 身份证 → L3(三要素组合,是实名认证基础,黑灰产核心目标);
    • 电子邮箱 → L2(单独),若用于重置密码或钓鱼攻击则为L3。

    CVV,全称是 Card Verification Value,中文常称为“信用卡安全码”或“卡片验证码”,是印在信用卡背面签名栏末端的一组3位或4位数字。它并非银行卡号的一部分,而是由发卡银行通过加密算法,结合卡号、有效期等信息生成的动态验证值,主要用于在非面对面交易(如网购、电话支付)中确认持卡人确实持有实体卡片,从而防止盗刷和欺诈。

    CVV 的核心作用是作为一道独立于密码和卡号的“第二道防线”。即使攻击者窃取了你的银行卡号和有效期,若没有 CVV,绝大多数线上支付平台会拒绝交易。因此,它在金融安全体系中属于最高敏感级别的数据,与密码、磁条数据一样,被严格禁止存储或记录在系统中。

    在很多国际支付场景(如 Visa/Mastercard 的境外网站)中,只要拥有“卡号 + 有效期 + CVV”这三样信息,就可以直接扣款,无需短信验证码。因此,CVV 本身就被视为具备直接造成资金损失能力的核心数据。

    根据国内《个人金融信息保护技术规范》及国际 PCI DSS 标准,CVV 被归类为 C3 级(最高敏感等级)或 L4 级数据,其安全防护要求极为严苛:

    • 严禁以任何形式明文存储;
    • 不得出现在日志、调试信息或第三方组件的输出中;
    • 传输过程必须加密;
    • 商户和系统端无权收集或保存,仅支付机构或银行可在交易瞬间临时验证。(即使加密存储也是违规的)

    只要涉及 CVV、磁道数据、支付密码 等直接用于资金交易的鉴权信息,都应毫不犹豫地将其定级为 L4,并采取最严格的加密传输、禁止落盘存储等防护措施。

    需要注意的是,分级不是静态的,它会随着数据组合、使用场景、行业属性动态调整。例如:

    • 单独的手机号是L2,但若与身份证号、住址组合,即构成“个人身份三要素”,应定为L3;
    • 企业在内部系统中存储的“统一社会信用代码”可能是L3,但若用于跨境数据传输或涉及国家经济命脉行业,则可能升级为L4;
    • 医疗系统中的“诊断结果”属于L3,但若涉及大规模人群健康数据,则可能被认定为L4。

    个人身份信息三要素通常指姓名、身份证号码和手机号码这三项核心信息,它们是当前国内实名认证、金融开户、网络注册等场景中用于验证用户真实身份的基础组合。

    三、为什么这些字段被标记为“敏感”?

    因为这些字段一旦泄露或被滥用,极易导致:

    • 个人层面:身份盗用、精准诈骗、骚扰电话、网络暴力;
    • 企业层面:客户信任崩塌、监管处罚、品牌声誉受损;
    • 社会层面:大规模数据泄露引发公共安全事件(如“社工库”泛滥)。

    尤其在金融、政务、医疗等行业,这些数据常被列为“重要数据”或“敏感个人信息”,需采取加密、脱敏、访问控制、审计日志等强化防护措施。

    四、如何进一步防护?
  • 最小化采集:非必要不收集敏感字段;
  • 动态脱敏:展示时对身份证号、手机号等做掩码处理(如 138****1234);
  • 访问控制:仅授权人员可访问原始数据,且需记录操作日志;
  • 加密存储:对密码、身份证号、银行卡号等字段加密存储;
  • 定期审计:监控异常访问行为,及时发现未鉴权接口或越权操作。
  • 📋 常见问题与解决方案

    基于“数安之江”专项检查,文档总结了电子政务领域存在的共性问题及改进建议:

    • 制度与人员管理:
      • 问题:安全制度模板化、应急预案流于形式、安全培训覆盖面不足、对第三方人员缺乏背景调查。
      • 对策:结合实际编制制度,落实应急责任人,加强全员(含驻场人员)安全培训,并对关键岗位的供应方人员进行背景审查。
    • 数据与权限管理:
      • 问题:数据资产底账不清、未开展分类分级、明文展示个人敏感信息、账号权限分配不合理(如三方人员权限过高)、重要账户密码交由第三方保管。
      • 对策:梳理数据资产并落实分类分级,对敏感信息进行脱敏或加密,遵循最小权限原则划分账号权限,核心账号密码应由内部人员严格管理。
    • 系统建设与运维:
      • 问题:缺乏日志审计功能、未定期进行应急演练和攻防演练、存在弱口令、应用存在未授权访问等漏洞。
      • 对策:完善系统日志记录与审计,定期组织演练,强制使用强密码策略(如8位以上,含三种字符),并在系统各阶段严格执行渗透测试和漏洞扫描。

    此外,文档还提出了“数据安全八准八不准”的行为准则,为单位人员和第三方服务人员划定了明确的安全红线,例如不准将生产数据直接用于测试、不准未经授权删除数据等,以规范日常操作,降低人为风险。

    实操

    — ==========================================
    — 1. 创建测试表并插入明文数据
    — ==========================================
    CREATE TABLE users (
    id INT PRIMARY KEY IDENTITY(1,1),
    username NVARCHAR(50),
    id_card NVARCHAR(18), — 身份证号 (待加密)
    phone NVARCHAR(20) — 手机号 (待脱敏)
    );

    — 插入几条测试数据
    INSERT INTO users (username, id_card, phone) VALUES
    ('张三', '330101199001011234', '13800001111'),
    ('李四', '330102199205055678', '13900002222'),
    ('王五', '330103198812129012', '13700003333');

    — 查看当前的明文数据
    SELECT * FROM users;

    完整逐行详解这段 SQL(SQL Server 语法)

    一、整体功能说明

    这段脚本分 3 段:

  • 创建一张用户测试表 users,存放用户名、身份证、手机号;
  • 插入 3 条测试明文数据;
  • 查询表内全部数据查看明文效果。 结合你之前的培训文档:id_card 身份证属于L4 敏感字段需加密存储,phone 手机号属于敏感字段需脱敏展示。
  • 二、分段逐句拆解

    第一段:创建测试表 CREATE TABLE

    CREATE TABLE users (
    id INT PRIMARY KEY IDENTITY(1,1),
    username NVARCHAR(50),
    id_card NVARCHAR(18), — 身份证号 (待加密)
    phone NVARCHAR(20) — 手机号 (待脱敏)
    );

  • CREATE TABLE users 创建一张名为 users 的数据表。
  • id INT PRIMARY KEY IDENTITY(1,1)
    • id INT:字段名称 id,类型整数;
    • PRIMARY KEY:主键,每条数据唯一标识,不可重复、不能为空;
    • IDENTITY(1,1):自增列,第一条数据 id=1,之后每条自动 + 1,无需手动赋值。
  • username NVARCHAR(50)
    • NVARCHAR:支持中文的可变长度字符串,N 代表 Unicode,避免中文乱码;
    • 最多存 50 个字符,存放用户名。
  • id_card NVARCHAR(18) 存储 18 位身份证号,注释标注待加密—— 对应培训里「数据加密能力」,真实生产不能明文存身份证,要加密入库。
  • phone NVARCHAR(20) 存储手机号,注释标注待脱敏—— 对应培训「数据脱敏能力」,前端 / 运维查询时不能完整展示,要隐藏中间数字。
  • 第二段:插入测试数据 INSERT

    INSERT INTO users (username, id_card, phone) VALUES
    ('张三', '330101199001011234', '13800001111'),
    ('李四', '330102199205055678', '13900002222'),
    ('王五', '330103198812129012', '13700003333');

  • INSERT INTO users (字段1,字段2,字段3):向 users 表指定字段写入数据;
  • VALUES 后跟 3 组数据,一次性插入 3 条用户明文信息;
  • 风险点(贴合培训案例):身份证、手机号明文存入数据库,一旦数据库被拖库、越权访问,直接造成公民个人信息泄露,就是文档里案例三的高危场景。
  • 第三段:查询查看明文数据 SELECT

    SELECT * FROM users;

    • SELECT *:查询表中所有字段;
    • FROM users:从 users 表读取; 执行后会完整输出:id、姓名、完整身份证、完整手机号,无任何隐藏 / 加密处理。

    三、结合你公共数据安全培训的风险解读

  • 违反数据分级管控要求 身份证 L4 级敏感数据,规范要求存储必须加密,此代码直接明文存储,存在泄露风险;
  • 缺少动态脱敏 手机号查询直接完整展示,运维、第三方人员访问时无法自动隐藏中间 4 位;
  • 无任何溯源防护 表内没有数据水印、操作日志,一旦数据导出泄露,无法定位是谁下载、何时导出;
  • 对应文档整改方案
    • 存储层:对 id_card 使用国密 SM4 加密存储;
    • 查询层:配置动态脱敏,phone 自动展示为 138****1111;
    • 管控层:增加接口审计、数据库操作日志,记录所有人查询、导出行为。
  • 四、补充语法说明

    这段是 SQL Server 专用语法:

    • IDENTITY(1,1) 自增是 SQL Server 独有;MySQL、Oracle 写法不同;
    • NVARCHAR 适配中文政务场景,政务系统通用。

    🛡️ 练习一:数据脱敏 (Dynamic Data Masking)

    这是最容易上手的一步,给手机号加上脱敏规则。

    — 给 phone 列添加脱敏规则:保留前3位和后4位,中间用 **** 代替
    ALTER TABLE users
    ALTER COLUMN phone ADD MASKED WITH (FUNCTION = 'partial(3,"****",4)');

    — 再次查询,你会发现手机号已经变成了 138****1111 这种格式
    SELECT * FROM users;

    — 【补充知识】如果你想临时取消脱敏(比如你是管理员需要看明文),可以执行:
    — GRANT UNMASK TO 你的当前用户名;

    1. 脱敏规则确实加上了,但你当前账号拥有 UNMASK 权限

    SQL Server 动态脱敏逻辑:

    • 给字段加 MASKED 只是定义脱敏模板,不是所有人查询都会自动打码;
    • 只有没有 UNMASK 权限的普通用户,查询才会显示 138****1111;
    • 管理员、DBA、sa 默认自带 UNMASK 权限,查询直接展示明文,和你截图现象完全一致。

    你代码里注释也写了:

    — GRANT UNMASK TO 你的当前用户名;

    这条语句就是授予「查看明文」权限,你当前登录账号已经被授予该权限,所以看不到脱敏效果。

    2. 完整分步拆解你这段代码

    — 给phone列绑定脱敏函数:前3位保留、中间4星、末尾4位
    ALTER TABLE users
    ALTER COLUMN phone ADD MASKED WITH (FUNCTION = 'partial(3,"****",4)');

    • partial(a,掩码,b):显示前 a 个字符 + 中间掩码 + 最后 b 个字符
    • 手机号 11 位:前 3 + **** + 后 4 = 138****1111,规则本身没问题,执行无报错说明规则创建成功。

    SELECT * FROM users;

    你当前账号有权限查看明文,所以结果还是完整手机号。

    二、两种验证脱敏效果的方法

    方法 1:新建一个普通测试账号,无 UNMASK 权限

    — 1. 创建测试用户
    CREATE USER test_user WITHOUT LOGIN;
    — 2. 授予查询表权限
    GRANT SELECT ON users TO test_user;
    — 3. 切换身份查询,能看到脱敏效果
    EXECUTE AS USER = 'test_user';
    SELECT * FROM users;
    — 切回原账号
    REVERT;

    执行后 phone 列就会变成 138****1111。

    方法 2:收回当前账号的明文查看权限(不建议生产管理员操作)

    REVOKE UNMASK FROM [你的登录账号名];

    收回后再 SELECT * FROM users,就自动脱敏; 需要看明文时再执行:

    GRANT UNMASK FROM [你的登录账号名];

    🔐 练习二:数据加密 (Always Encrypted)

    注意: 这个功能在 SSMS 里必须通过向导界面操作,不能直接用 SQL 语句一键完成。

    (我当前连接的是 Azure SQL Database 或者是一个较新版本的 SQL Server,它的菜单结构变了,把“Always Encrypted”向导移到了别的地方,或者直接不支持这种老式的图形化向导操作了。所以这次还是使用代码操作)

    实操步骤:

  • 在左侧的“对象资源管理器”中,展开你的数据库 -> 表 -> 找到 users 表。
  • 右键点击 users 表,选择 “加密列” (Encrypt Columns)。
  • 在弹出的窗口中,勾选 id_card 列。
  • 加密类型选择 “确定性” (Deterministic)(这样加密后的数据才能用于等值查询,比如 WHERE id_card = '…')。
  • 一路点击“下一步”,在配置主密钥那一步,选择 “Windows 证书存储 – 当前用户”。
  • 点击“完成”并执行。
  • 执行完毕后,你再去执行 SELECT * FROM users;,会发现 id_card 列的数据变成了一串乱码!这就说明加密成功了。

    第一步:基于证书创建一个对称密钥

    — 1. 如果还没有数据库主密钥,先创建一个(通常都有,没有再开)
    IF NOT EXISTS (SELECT * FROM sys.symmetric_keys WHERE symmetric_key_id = 101)
    CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'MyStrongPassword123!';
    GO

    — 2. 创建一个证书
    CREATE CERTIFICATE UserCert WITH SUBJECT = 'User Data Protection';
    GO

    — 3. 基于证书创建一个对称密钥 (AES_256 算法)
    CREATE SYMMETRIC KEY UserKey
    WITH ALGORITHM = AES_256
    ENCRYPTION BY CERTIFICATE UserCert;
    GO

    完整逐行详解(SQL Server 列加密 / 存储加密整套流程,对应你培训里数据加密安全能力,用来加密身份证这类 L4 高敏感字段)

    整体作用

    这三段 SQL 是搭建数据库对称加密环境,用来把身份证号这类核心敏感数据加密存库(底层不再保存明文,和刚才手机号「查询脱敏」完全是两种安全方案)。 整套链路:数据库主密钥 → 证书 → 对称密钥,三层加密保护加密密钥本身,防止密钥泄露。

    1. 第一段:判断并创建【数据库主密钥 Database Master Key】

    IF NOT EXISTS (SELECT * FROM sys.symmetric_keys WHERE symmetric_key_id = 101)
    CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'MyStrongPassword123!';
    GO

    逐句拆解
  • sys.symmetric_keys SQL Server 系统内置视图,记录当前库所有密钥;symmetric_key_id = 101 是数据库主密钥固定 ID。
  • IF NOT EXISTS(…) 判断逻辑:如果当前数据库不存在主密钥,才执行创建;已有就跳过,避免重复创建报错。
  • CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'xxx'
    • 数据库主密钥(DMK):当前数据库所有加密体系的根钥匙,是整套加密的起点;
    • 作用:用来加密后面创建的证书、对称密钥;
    • 必须设置高强度密码,生产环境不能写死明文在脚本里。
  • GO SQL Server 批处理分隔符,把这段单独执行。
  • 业务理解

    没有主密钥,后面证书、加密密钥全都建不了;相当于你家里保险箱的总钥匙。

    2. 第二段:创建加密证书 Certificate

    CREATE CERTIFICATE UserCert WITH SUBJECT = 'User Data Protection';
    GO

  • CREATE CERTIFICATE UserCert 创建一张名为 UserCert 的数据库内置证书;
  • WITH SUBJECT = 'User Data Protection' 证书备注主题,标注用途:用户敏感数据保护;
  • 证书作用 用证书的非对称密钥,保护下一层的对称密钥。

    行业规范:非对称加密(证书)用来保护密钥,对称加密(AES)用来加密业务数据,兼顾安全和性能。

  • 3. 第三段:创建业务对称密钥 UserKey(真正加密身份证的工具)

    CREATE SYMMETRIC KEY UserKey
    WITH ALGORITHM = AES_256
    ENCRYPTION BY CERTIFICATE UserCert;
    GO

  • CREATE SYMMETRIC KEY UserKey 创建对称密钥 UserKey,这是最终用来加密 / 解密身份证号的密钥;
  • WITH ALGORITHM = AES_256 指定加密算法:AES-256,国际通用高强度对称加密;

    政务等等保合规场景会替换为国密 SM4 算法。

  • ENCRYPTION BY CERTIFICATE UserCert 声明:这把对称密钥本身,由上面创建的 UserCert 证书加密保护。 密钥不会裸存,必须靠证书才能打开使用。
  • 整套加密层级关系(从上到下)

  • 数据库主密钥(DMK,ID=101)→ 加密保护证书
  • 证书 UserCert → 加密保护对称密钥 UserKey
  • 对称密钥 UserKey → 真正加密 id_card 身份证明文数据
  • 和之前手机号脱敏做对比(核心区分两大安全能力)

    方案本段代码(存储加密)之前 MASK 动态脱敏(展示脱敏)
    存储层 数据库里存密文,无原始明文 数据库底层依旧存完整明文
    生效时机 写入数据时加密,读取时解密 仅查询展示时隐藏,底层不变
    适用数据 身份证、银行卡(L4 最高敏感) 手机号、住址(L3 普通敏感)
    泄露风险 就算数据库被拖库,拿到密文无法还原 拖库后直接拿到完整原始数据
    权限管控 必须打开密钥才能解密查看明文 仅区分 UNMASK 权限控制展示

    第二步:修改表结构

    原来的 id_card 存的是明文(字符串),加密后变成乱码(二进制),所以我们需要加一列来存密文。

    — 添加一个新列用来存加密后的数据 (varbinary 类型)
    ALTER TABLE users ADD id_card_encrypted VARBINARY(256);
    GO

    第三步:执行加密 (把明文变密文)

    这一步就是真正的“加密”动作了!

    — 打开刚才创建的钥匙
    OPEN SYMMETRIC KEY UserKey DECRYPTION BY CERTIFICATE UserCert;

    — 更新数据:把 id_card 的内容加密后写入新列
    UPDATE users
    SET id_card_encrypted = EncryptByKey(Key_GUID('UserKey'), id_card);
    GO

    — 用完记得关钥匙
    CLOSE SYMMETRIC KEY UserKey;
    GO

    可能出现的问题:权限不足

    解决办法:🔍 怎么找到并确认你的账号身份?

    — 查看当前连接的“登录名”和“数据库用户”
    SELECT
    SYSTEM_USER AS '当前登录名(Login)',
    USER_NAME() AS '当前数据库用户(User)',
    IS_SRVROLEMEMBER('sysadmin') AS '是否是管理员(1是0否)';

    • 如果 当前数据库用户 显示的是 test:那就实锤了!你现在就是那个低权限用户,所以刚才报“无法查找密钥”的错。
    • 如果 是否是管理员 显示为 0:说明你现在的权限确实不够,必须切换。

    🔄 如何切换回管理员账号?

    既然你在左侧看不到 test,说明你可能是用 Windows 认证直接连进来的,或者之前的连接缓存了。请按以下步骤强制切换:

  • 断开连接:在 SSMS 左侧最顶部的服务器图标上右键 -> 断开连接。
  • 重新连接:再次右键 -> 连接 -> 数据库引擎。
  • 关键一步:在弹出的登录框中,不要直接点连接。
    • 确保“身份验证”选择的是 SQL Server 身份验证。
    • 登录名输入:sa
    • 密码:输入你安装 SQL Server 时设置的 sa 密码(如果你没改过,通常是安装时设的那个强密码)。
  • 连接成功后:再次运行上面的 SELECT SYSTEM_USER… 代码,确认显示的是 sa 且管理员权限为 1。
  • 💡 为什么一定要切回 sa?

    因为创建密钥 (Create Key) 和 修改表结构 (Alter Table) 是只有“房东”(管理员)才能干的事。“租客”(test 用户)只能负责“住”(查询数据)。

    等你切回 sa 账号,把刚才那段加密代码跑通,看到了 0x… 的密文,咱们再切回 test 账号去测试“解密”,那样你就能亲眼看到:同样的表,管理员看是明文/密文,租客看全是乱码或星号,这个对比效果非常棒!

    那如果显示的是1,也就是已经是管理员权限了呢?

    刚才报错说“找不到密钥”,那原因就只有一个了:钥匙还没造出来,或者造的时候报错了导致没成功。

    别管那个 test 用户了,咱们直接用现在这个“超级管理员”身份,把钥匙造出来,把数据加密了。

    🚀 立即执行:一键生成密钥并加密

    请直接复制下面这段代码,在当前的查询窗口里全部选中,然后点“执行”。这段代码我加了“防呆设计”,如果之前有残留会先清理,确保能跑通:

    — ==========================================
    — 第一步:清理旧环境 & 创建新钥匙
    — ==========================================

    — 1. 如果之前有同名的密钥,先删掉(防止重名报错)
    IF EXISTS (SELECT * FROM sys.symmetric_keys WHERE name = 'UserKey')
    DROP SYMMETRIC KEY UserKey;
    GO

    — 2. 如果之前有同名的证书,先删掉
    IF EXISTS (SELECT * FROM sys.certificates WHERE name = 'UserCert')
    DROP CERTIFICATE UserCert;
    GO

    — 3. 创建证书
    CREATE CERTIFICATE UserCert WITH SUBJECT = 'User Data Protection';
    GO

    — 4. 创建对称密钥 (这是真正的加密核心)
    CREATE SYMMETRIC KEY UserKey
    WITH ALGORITHM = AES_256
    ENCRYPTION BY CERTIFICATE UserCert;
    GO

    — ==========================================
    — 第二步:准备存密文的列
    — ==========================================

    — 检查表里有没有 id_card_encrypted 这一列,没有就加上
    IF COL_LENGTH('users', 'id_card_encrypted') IS NULL
    BEGIN
    ALTER TABLE users ADD id_card_encrypted VARBINARY(256);
    PRINT '✅ 新列 id_card_encrypted 创建成功';
    END
    ELSE
    BEGIN
    PRINT '⚠️ 列已存在,直接进行下一步';
    END
    GO

    — ==========================================
    — 第三步:打开钥匙,执行加密!
    — ==========================================

    — 1. 打开钥匙
    OPEN SYMMETRIC KEY UserKey DECRYPTION BY CERTIFICATE UserCert;

    — 2. 更新数据:把明文(id_card)加密后写入新列(id_card_encrypted)
    UPDATE users
    SET id_card_encrypted = EncryptByKey(Key_GUID('UserKey'), id_card);

    — 3. 用完随手关门(安全好习惯)
    CLOSE SYMMETRIC KEY UserKey;
    GO

    — ==========================================
    — 第四步:验收成果
    — ==========================================
    SELECT
    username,
    id_card AS '原始明文',
    id_card_encrypted AS '加密后的密文(乱码)'
    FROM users;

    💡 预期结果

    执行完后,下方的结果网格应该会出现三列:

  • username: 张三、李四…
  • 原始明文: 正常的身份证号。
  • 加密后的密文: 一长串以 0x 开头的乱码(例如 0x008923A1…)。
  • 第四步:验证成果

    现在你可以查询看看效果:

    — 查看对比
    SELECT
    username,
    id_card AS '原始明文',
    id_card_encrypted AS '加密后的密文'
    FROM users;

    你会看到 id_card_encrypted 列是一串 0x… 开头的乱码,这就代表加密成功了!

    数据加密能力

    核心定义:敏感数据在存储、传输全过程用密码算法加密,防泄露、篡改、冒充、抵赖,政务场景强制优先使用国密 SM 系列算法,配套合规要求。 整体四层合规链条:密码算法合规 → 密码技术合规 → 商用密码产品认证 → 密码服务许可。

    1、四大安全威胁、对应安全目标、加密技术、国密 / 国际算法对照表

    威胁类型风险说明安全目标密码技术国产国密算法国际通用算法

    窃听(秘密泄露)

    数据被偷看到明文,比如数据库拖库、传输抓包 机密性 对称密码(加密存 / 传数据) SM1、SM4、ZUC、SM7 AES、DES、3DES
    否认(事后抵赖) 做完操作不认账,比如泄露后说不是自己导出数据 不可否认性 公钥密码(数字签名、证书) SM2、SM9 RSA、ECC

    篡改(信息被修改)

    数据中途被篡改,比如身份证、金额被改 完整性 单向散列函数 SM3 MD5、SHA
    伪装(冒充发送方) 黑客伪造接口、账号冒充合法人员访问 身份认证 MAC/HMAC 消息验证码 搭配 SM3 实现 MD5-HMAC、SHA-HMAC

    2、三类密码技术通俗解释(结合刚写的 SQL 加密代码)

    (1)对称密码(SM4/AES)

    • 作用:加密业务敏感数据(身份证、手机号存储加密),解决「窃听、机密性」;
    • 对应代码:AES_256 就是国际对称算法;政务要替换成国密 SM4;
    • 特点:加密、解密用同一把密钥,速度快,适合大批量业务数据加密。

    (2)公钥密码(SM2/RSA)

    • 作用:做证书、数字签名,解决「抵赖、身份认证」;
    • 对应代码:脚本里的CERTIFICATE证书就是基于非对称公钥密码;
    • 特点:一对公私钥,公钥加密、私钥解密,用来保护对称密钥、做操作签名留痕溯源。

    (3)单向散列(SM3/SHA)

    • 作用:校验数据有没有被篡改,不可逆(不能还原原文);
    • 场景:密码哈希存储、接口数据完整性校验;
    • 特点:原文改一个字符,哈希值完全变化,无法反向算出原始数据。

    3、和刚才两段 SQL 代码对应联动(打通实操 + 理论)

  • 数据库存储加密脚本(主密钥 + 证书 + AES 对称密钥)
    • AES256 = PPT 里国际对称算法;政务合规替换为国密 SM4;
    • CERTIFICATE 证书 = PPT 公钥密码技术(SM2 对应国密证书);
    • 用途:实现存储加密,解决「窃听、数据泄露」,对应 PPT 第一条威胁防护。
  • 之前手机号MASKED动态脱敏
    • 不属于加密能力!只是前端展示隐藏,底层数据仍是明文;
    • 「数据加密能力」特指存储 / 传输底层密文防护,脱敏是配套辅助能力,二者不能互相替代。
  • 🔑 练习三:权限管控 (Permission Control)

    你可以建一个普通账号,测试一下他是不是真的看不到敏感数据。

    — 1. 创建一个专门用来测试的普通登录账号
    CREATE LOGIN test_user WITH PASSWORD = 'Test@123456';

    — 2. 在当前数据库下为这个登录名创建一个用户
    CREATE USER test_user FOR LOGIN test_user;

    — 3. 给这个用户赋予查询 users 表的权限
    GRANT SELECT ON users TO test_user;

    — 4. 测试权限(你可以右键点击数据库,选择“更改连接”,用 test_user 的身份连进去查一下)
    — 你会发现,test_user 查出来的数据是脱敏后的,且无法执行增删改操作。

    — 5. 练习清理(练完手后,把测试账号删掉)
    — REVOKE SELECT ON users TO test_user;
    — DROP USER test_user;
    — DROP LOGIN test_user;

    — ==========================================
    — 1. 给已经存在的 test_user2 补发“查看权限”
    — ==========================================
    GRANT SELECT ON dbo.Users TO test_user2;
    GO

    — ==========================================
    — 2. 验证权限是否生效
    — ==========================================
    — 模拟 test_user2 的身份来查询(不用切换窗口,直接用这句命令)
    EXECUTE AS USER = 'test_user2';
    SELECT
    SYSTEM_USER AS '当前模拟登录名',
    USER_NAME() AS '当前数据库用户',
    *
    FROM dbo.Users;
    REVERT; — 恢复回 sa 身份
    GO

    练习四:添加水印

    💧 玩法一:查询层水印(最简单,适合导出溯源)

    这种水印是在数据导出或查询时,动态拼接上去的。比如你要把用户数据导出给第三方公司,可以在数据里偷偷加一个“追踪 ID”。

    实操代码: 假设你要把数据给“A公司”,可以执行以下查询:

    — 在查询结果中动态附加一个隐藏的水印标识
    SELECT
    username,
    id_card,
    phone,
    'WATERMARK_FOR_COMPANY_A_20260713' AS trace_id — 这就是你的水印
    FROM dbo.Users;

    效果:如果未来这批数据泄露了,你看到数据里带有 COMPANY_A 的标识,就能立刻锁定是提供给 A 公司的那批数据出了问题。


    🧬 玩法二:存储层水印(进阶,适合防篡改)

    这种水印是直接把信息“藏”进数据库的表结构里。我们可以利用 SQL Server 的默认值来实现。

    实操代码: 我们可以给 users 表加一个默认带水印的列。

    — 1. 给表增加一个专门存水印的列(默认值为当前数据库用户或特定标识)
    ALTER TABLE dbo.Users
    ADD data_watermark NVARCHAR(100) DEFAULT (SYSTEM_USER + '_DB_TRACE');
    GO

    — 2. 查看效果(你会发现新插入的数据自动带上了水印)
    SELECT * FROM dbo.Users;

    效果:即使黑客拖走了数据库,或者内部人员偷偷复制了数据,只要数据还在,这个 data_watermark 列就会像幽灵一样跟着,证明这批数据是从哪个环境、哪个账号流出去的。

    🧐 为什么是 NULL?

    SQL Server 的 DEFAULT(默认值)机制有个特点:它只在“新插入”数据时生效。 对于表里原本就存在的“老数据”(张三、李四、王五),数据库不会自动回头去给它们补填这个默认值,所以它们依然显示为空(NULL)。

    🛠️ 怎么让老数据也带上水印?

    只需要执行一条简单的 UPDATE 语句,强制刷新一下这几行数据即可。

    请在当前窗口继续执行以下代码:

    — 1. 刷新老数据:把 watermark 列更新为默认值
    — 这里的逻辑是:只要这一行是 NULL,就把它更新为系统生成的默认值
    UPDATE dbo.Users
    SET data_watermark = DEFAULT
    WHERE data_watermark IS NULL;

    — 2. 再次查看效果
    SELECT * FROM dbo.Users;

    💡 预期结果

    执行完上面的 UPDATE 后,你应该会看到 data_watermark 这一列变成了类似这样的内容:

    • sa_DB_TRACE (因为你现在是用 sa 账号在执行更新操作)
    🚀 下一步验证(见证奇迹的时刻)

    为了让这个水印真正发挥作用,你可以试着插入一条新数据,看看它是不是自动就带上了水印,而不需要手动去填:

    — 3. 测试插入新数据(故意不写 watermark 列)
    INSERT INTO dbo.Users (username, id_card, phone)
    VALUES ('赵六', '330106200001019999', '15900006666');

    — 4. 查看最终结果
    SELECT * FROM dbo.Users;

  • 老数据复活:张三、李四、王五的 data_watermark 列都已经成功刷上了 sa_DB_TRACE。
  • 自动防御生效:新插入的“赵六”,虽然你在 INSERT 语句里根本没提水印这回事,但系统自动给他打上了 sa_DB_TRACE 标签。这就是 DEFAULT 约束的威力——无感植入。
  • 溯源逻辑成立:因为你是用 sa 账号执行的更新和插入,所以水印前缀是 sa。如果将来有个黑客用 test_user2 偷偷插了一条脏数据,那个水印就会变成 test_user2_DB_TRACE,一眼就能抓出内鬼!
  • ⚠️ 发现一个小盲点

    请注意看“赵六”那一行的 id_card_encrypted 列(倒数第二列),它是 NULL。

    这是因为我们刚才只给表加了“水印列”的默认值,但没给“加密列”加。如果业务上要求所有入库的身份证必须加密,光靠应用层代码是不够的(万一有人绕过代码直接插库呢?)。

    我们可以把这个“加密动作”也自动化,做成一个触发器 (Trigger)。这样无论谁、用什么方式插数据,身份证号都会自动变密文。

    🛡️ 自动加密触发器代码

    — ==========================================
    — 1. 创建触发器: trg_Encrypt_IDCard
    — 作用:当有新数据插入或更新时,自动把 id_card 加密写入 id_card_encrypted
    — ==========================================
    CREATE TRIGGER trg_Encrypt_IDCard
    ON dbo.Users
    AFTER INSERT, UPDATE
    AS
    BEGIN
    — 关闭影响行数提示,防止干扰程序
    SET NOCOUNT ON;

    — 检查是否开启了密钥(必须打开才能加密)
    IF NOT EXISTS (SELECT * FROM sys.symmetric_keys WHERE name = 'SymKey_Users' AND is_open = 1)
    BEGIN
    OPEN SYMMETRIC KEY SymKey_Users DECRYPTION BY CERTIFICATE Cert_Users;
    END

    — 核心逻辑:更新刚刚插入/修改的那几行数据
    UPDATE u
    SET u.id_card_encrypted = EncryptByKey(Key_GUID('SymKey_Users'), i.id_card)
    FROM dbo.Users u
    INNER JOIN inserted i ON u.id = i.id;
    END;
    GO

    PRINT '✅ 触发器创建成功!以后插入数据会自动加密。';

    这是一个典型的“假报错”现象。

  • 红色报错:是因为系统视图 sys.symmetric_keys 里确实没有叫 is_open 的列(密钥状态通常存在会话上下文里,而不是这个静态视图里)。
  • 绿色成功提示:说明 SQL Server 忽略了这个逻辑错误,依然把触发器的“壳子”建好了。
  • 但是!如果现在直接去插入数据,触发器会在运行时再次报错并导致插入失败。 我们需要把这个“有缺陷”的触发器删掉,换一个绝对稳健的版本。

    🛠️ 修复方案:使用“先开后用”策略

    在触发器里去“检查”密钥是否打开非常麻烦且容易出错。最简单的做法是:不管它开没开,每次进来都强制打开一次。SQL Server 很聪明,如果密钥已经开了,重复执行 OPEN 是不会报错的。

    请复制下面这段修正版代码,它会先删除旧触发器,再创建新的:

    — ==========================================
    — 1. 删除刚才那个有瑕疵的触发器
    — ==========================================
    IF OBJECT_ID('trg_Encrypt_IDCard', 'TR') IS NOT NULL
    DROP TRIGGER trg_Encrypt_IDCard;
    GO

    — ==========================================
    — 2. 创建修正后的触发器 (稳健版)
    — ==========================================
    CREATE TRIGGER trg_Encrypt_IDCard
    ON dbo.Users
    AFTER INSERT, UPDATE
    AS
    BEGIN
    SET NOCOUNT ON;

    — 【核心修改】不再检查状态,直接强制打开密钥
    — 如果密钥已经打开,这句不会报错;如果没开,这句会打开它。
    OPEN SYMMETRIC KEY SymKey_Users DECRYPTION BY CERTIFICATE Cert_Users;

    — 执行加密更新
    UPDATE u
    SET u.id_card_encrypted = EncryptByKey(Key_GUID('SymKey_Users'), i.id_card)
    FROM dbo.Users u
    INNER JOIN inserted i ON u.id = i.id;
    END;
    GO

    PRINT '✅ 修正版触发器已就绪!';

    🧪 验证测试(见证奇迹的时刻)

    现在我们来测试一下。为了证明触发器生效了,我们先删掉刚才那个没加密的“赵六”,然后重新插入一个“赵六”。

    — 1. 删除旧的“赵六”(那个加密列是 NULL 的)
    DELETE FROM dbo.Users WHERE username = '赵六';

    — 2. 重新插入“赵六”(这次故意只写明文身份证)
    INSERT INTO dbo.Users (username, id_card, phone)
    VALUES ('赵六', '330106200001019999', '15900006666');

    — 3. 查看结果
    SELECT * FROM dbo.Users WHERE username = '赵六';

    可能出现的问题:

    为什么会报错?

    报错信息说:无法对对称密钥 'SymKey_Users' 执行查找,因为它不存在…

    原因很简单:“钥匙”还没拿出来。 在 SQL Server 中,加密用的对称密钥默认是关闭的。每次打开一个新的查询窗口(Query Window),或者重启服务后,你都必须先手动执行一句 OPEN SYMMETRIC KEY,数据库才知道怎么用它来加密数据。

    刚才我们删掉了“赵六”,现在重新插入时,触发了自动加密逻辑,但因为你在这个新窗口里还没把密钥“打开”,所以触发器拿着明文身份证想去加密时,发现手里没钥匙,就报错了。

    🛠️ 解决方法(只需两步)

    请在当前窗口的最上方,加上打开密钥的代码,然后再执行插入操作。

    第一步:打开密钥(必做!)

    — 必须先执行这句,告诉数据库把保险箱打开
    OPEN SYMMETRIC KEY SymKey_Users
    DECRYPTION BY CERTIFICATE Cert_Users;
    GO

    如果执行这个出现报错:

    这意味着:在这个数据库里,根本就没有叫 SymKey_Users 的对称密钥。之前的触发器之所以能创建成功,是因为创建触发器时不会检查密钥是否存在,只有真正执行加密动作时才会发现“查无此钥”。

    看来我们需要从头把“加密基础设施”搭建起来。请按照以下顺序,一步步执行代码:

    🛠️ 第一步:确认并创建证书

    对称密钥必须依附于一个证书。我们先检查一下证书在不在,如果不在就创建一个。

    — 检查证书是否存在
    IF NOT EXISTS (SELECT * FROM sys.certificates WHERE name = 'Cert_Users')
    BEGIN
    CREATE CERTIFICATE Cert_Users WITH SUBJECT = 'User Data Protection';
    PRINT '✅ 证书 Cert_Users 创建成功';
    END
    ELSE
    PRINT 'ℹ️ 证书 Cert_Users 已存在';
    GO

    🔑 第二步:创建对称密钥

    这是核心步骤。我们将创建一个名为 SymKey_Users 的密钥,并用刚才的证书保护它。

    — 检查密钥是否存在
    IF NOT EXISTS (SELECT * FROM sys.symmetric_keys WHERE name = 'SymKey_Users')
    BEGIN
    CREATE SYMMETRIC KEY SymKey_Users
    WITH ALGORITHM = AES_256
    ENCRYPTION BY CERTIFICATE Cert_Users;

    PRINT '✅ 对称密钥 SymKey_Users 创建成功';
    END
    ELSE
    PRINT 'ℹ️ 对称密钥 SymKey_Users 已存在';
    GO

    🔄 第三步:重建触发器

    既然密钥刚刚被我们“生”出来了,为了确保万无一失,我们把之前的触发器删掉重建一下(防止之前的缓存问题)。

    — 删除旧触发器
    IF OBJECT_ID('trg_Encrypt_IDCard', 'TR') IS NOT NULL
    DROP TRIGGER trg_Encrypt_IDCard;
    GO

    — 创建新触发器
    CREATE TRIGGER trg_Encrypt_IDCard
    ON dbo.Users
    AFTER INSERT, UPDATE
    AS
    BEGIN
    SET NOCOUNT ON;

    — 强制打开密钥(现在它确实存在了)
    OPEN SYMMETRIC KEY SymKey_Users DECRYPTION BY CERTIFICATE Cert_Users;

    — 执行加密更新
    UPDATE u
    SET u.id_card_encrypted = EncryptByKey(Key_GUID('SymKey_Users'), i.id_card)
    FROM dbo.Users u
    INNER JOIN inserted i ON u.id = i.id;
    END;
    GO

    PRINT '✅ 触发器重建完成,基础设施就绪!';

    🧪 第四步:最终验证

    现在环境已经干净了,我们可以重新测试“赵六”的插入。

    — 1. 清理旧数据
    DELETE FROM dbo.Users WHERE username = '赵六';

    — 2. 插入新数据(测试自动加密)
    INSERT INTO dbo.Users (username, id_card, phone)
    VALUES ('赵六', '330106200001019999', '15900006666');

    — 3. 查看结果
    SELECT * FROM dbo.Users WHERE username = '赵六';

    💡 为什么之前会这样?

    很可能是因为在之前的某个环节,创建密钥的代码没有执行成功(比如被跳过了,或者在另一个窗口执行了但没提交/没同步过来),导致表结构和触发器都建好了,但底层的“钥匙”却丢了。

    💡 预期结果

    执行完上面的查询后,你会发现“赵六”这一行的 id_card_encrypted 不再是 NULL,而是一串以 0x00… 开头的乱码密文了!

    这就意味着,你的表现在拥有了双重自动化防御:

  • 水印自动打(通过 DEFAULT 约束)。
  • 身份证自动加密(通过 Trigger 触发器)。
  • 赞(0)
    未经允许不得转载:171主机测评 » 运维--数据资源管理
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址