用于编写屏蔽数据的字段过程的准则
字段过程可用于在解码数据时屏蔽特定用户或环境的数据。 必须对屏蔽数据的字段过程进行编码以处理特殊情况,以确保数据未损坏。
以下特殊情况必须由屏蔽数据的字段过程处理:
- 字段解码
- 必须仅对字段解码执行屏蔽。 不得对字段编码执行此操作。 如果对字段编码执行了屏蔽,那么屏蔽的数据将存储在表中,并且实际值将丢失。
- 在某些情况下,系统代码需要在内部复制数据 (在这些情况下不会将数据返回给用户)。 例如,在某些情况下, RGZPFM , ALTER TABLE 和 CRTDUPOBJ 必须在内部复制数据。 同样,不得屏蔽内部传递给触发器的数据。 在这些操作期间,当读取数据时,将进行字段解码,当写入数据时,将进行字段编码。 如果在字段解码期间在这些情况下执行屏蔽,那么将写入掩码数据,并且实际数据将丢失。
为了防止损坏,字段过程的第九个参数指示这是否是不得执行屏蔽的系统操作。 关键是在字段解码期间写入字段过程以检查此参数,如果该参数指示不得执行屏蔽,那么字段过程不得屏蔽,无论用户或环境如何。
- 字段编码
- 对于本机更新和插入操作,字段过程必须能够识别何时将掩码数据传递到字段过程并执行特殊操作。 例如,可以编写字段过程以屏蔽信用卡号列。 可授权同一用户通过执行 READ 和 UPDATE 操作的 RPG 应用程序来读取和更新表。 执行 READ 时,会屏蔽信用卡号以防止用户看到它,但当用户执行 UPDATE 时,会将屏蔽的数据传递回 UPDATE 操作上的数据库,并将调用字段过程对数据进行编码。 如果字段过程不识别所传递的值是掩码值,那么将对掩码数据进行编码并将其存储在表中,并且行中的原始值将被编码的掩码数据损坏。为了防止损坏,字段过程必须在字段编码上识别数据已被屏蔽。 字段过程必须在第七个参数中返回警告 SQLSTATE 值 "09501" ,而不是对数据进行编码。
- 对于 UPDATE 操作,"09501 "表示 Db2® 应使用列的当前值。
- 对于 INSERT 操作, "09501" 向 Db2 指示应该将缺省值用于关联的列值。
- 对于本机更新和插入操作,字段过程必须能够识别何时将掩码数据传递到字段过程并执行特殊操作。 例如,可以编写字段过程以屏蔽信用卡号列。 可授权同一用户通过执行 READ 和 UPDATE 操作的 RPG 应用程序来读取和更新表。 执行 READ 时,会屏蔽信用卡号以防止用户看到它,但当用户执行 UPDATE 时,会将屏蔽的数据传递回 UPDATE 操作上的数据库,并将调用字段过程对数据进行编码。 如果字段过程不识别所传递的值是掩码值,那么将对掩码数据进行编码并将其存储在表中,并且行中的原始值将被编码的掩码数据损坏。
查询注意事项: 有几个注意事项适用于引用具有屏蔽数据的字段过程的表列的查询:
- 根据优化器实现查询的方式,同一查询可能会针对不同的用户或环境返回不同的行和值。 如果优化器必须对数据进行解码才能在查询中执行比较或对表达式进行求值,那么将发生此情况。 如果对一个用户执行屏蔽,但不对另一个用户执行屏蔽,那么解码操作的结果将非常不同,因此生成的行和值对于这两个用户也可能大相径庭。例如,假定字段过程返回 (解码) 用户概要文件 MAIN 的数据而不进行屏蔽,并返回 (解码) 具有屏蔽的用户概要文件 QUSER 的数据。 应用程序包含以下查询:
缺省情况下,优化器将尝试实现搜索条件 (逻辑上) ,如下所示:SELECT * FROM orders WHERE cardnum = '112233'
这是性能最佳的实现,因为它允许 Db2 将常量 "112233" 的编码版本与存储在订单表中的 CARDNUM 值的编码版本进行比较。 由于优化器未对数据进行解码以执行比较,因此对于 MAIN 和 QUSER 用户概要文件,查询将返回相同的行。 唯一的区别是 QUSER 将在 CARDNUM 列的结果行中看到掩码值。WHERE cardnum = FieldProc ENCODE('112233')引用字段过程列的查询的实现可由 QAQQINI FIELDPROC_ENCODED_比较选项控制。 此选项的缺省值为 *ALLOW_EQUAL。 此选项使优化器能够使用编码值来实现比较。
在先前的示例中,如果FIELDPROC_ENCODED_比较选项更改为 *NONE ,那么查询将为两个用户返回不同的行。 当该值为 *NONE 时, Db2 将在内部实现相等的比较,如下所示:
在这种情况下, Db2 必须对表中每行的 CARDNUM 值进行解码,以与原始常量 "112233" 进行比较。 这意味着 MAIN 用户概要文件的比较将解码和未屏蔽的卡号值 (112233 , 332211 等) 与 "112233" 进行比较。 MAIN 用户概要文件将查找与指定卡号 (112233) 关联的订单。 但是,查询不会返回 QUSER 用户概要文件的任何行。 这是因为 QUSER 的比较将卡号 (* *** 33 , **** 11 等) 的掩码值与常量 "112233" 进行比较。WHERE FieldProc DECODE(cardnum)='112233'有关 QAQQQINI FIELDPROC_ENCODED_比较选项如何影响字段过程的更多信息,请参阅 "信息中心" 中的 "数据库性能和查询优化" 主题。
- 具体化查询表的刷新受 QAQQINI FIELDPROC_ENCODED_比较选项影响。 如果具体化查询表引用具有屏蔽字段过程的列,那么必须由允许查看未屏蔽数据的用户发出 MQT 的 REFRESH。 否则, MQT 中的结果将对所有用户不正确。
- CREATE TABLE LIKE , CREATE TABLE AS , DECLARE GLOBAL TEMPORARY TABLE LIKE 或 DECLARE GLOBAL TEMPORARY TABLE AS 受 QAQQINI FIELDPROC_ENCODED_经比较选项影响。 如果语句由不允许查看未屏蔽数据的用户发出,那么生成的表将包含屏蔽数据。
- OPNQRYF和 Query/400 不受QAQQINI FIELDPROC_ENCODED_COMPARISON选项的影响。 优化器始终通过解码值 (类似于FIELDPROC_ENCODED_比较选项 *NONE) 进行处理。
- 选择/省略 DDS 创建的逻辑文件也不受 QAQQINI FIELDPROC_ENCODED_比较选项的影响。 通过解码值 (类似于FIELDPROC_ENCODED_比较选项 *NONE) 来处理逻辑文件。
最佳实践: 如果您具有屏蔽数据的字段过程,那么强烈建议使用两个 QAQQINI 选项:
- FIELDPROC_ENCODED_COMPARISON
- FIELDPROC_ENCODED_比较的缺省选项是 *ALLOW_EQUAL ,这对于不屏蔽数据的字段过程非常有效。 但是,如果使用了用于屏蔽数据的字段过程,那么 *NONE 是最安全的建议选项。
- CACHE_RESULTS
- CACHE_RESULTS 的缺省选项为 *SYSTEM。 在许多情况下,此选项运行良好。 但是,如果使用了屏蔽数据的字段过程,那么应该为 CACHE_RESULTS 指定 *JOB。
由于这两个选项会影响屏蔽数据的字段过程的行为,因此确保仅允许授权用户指定新的或不同的 QAQQINI 选项也很重要:
- CHGQRYA 命令
验证只有授权用户才能执行 CHGQRYA 命令。 缺省情况下,只有具有作业控制 (*JOBCTL) 特权或具有 QIBM_DB_SQLADM 功能用法的用户才有权使用 CHGQRYA 命令。
- QUSRSYS/QAQQINI 文件
验证只有授权用户才能创建 QUSRSYS/QAQQINI 文件或更新它 (如果它已存在)。 缺省情况下, *PUBLIC 对 QUSRSYS 具有 *USE 权限,该权限不足以创建新的 QUSRSYS.QAQQINI 文件。