本教程介绍了如何在 Spanner 中使用参数化视图,以根据应用安全传递的参数来限制对数据的访问。
如需详细了解参数化视图,请参阅参数化视图概览。
目标
- 创建包含示例数据的表。
- 创建一个参数化视图,用于根据安全上下文参数过滤数据。
- 为精细访问权限控制创建一个数据库角色,供应用用于连接到数据库和访问参数化视图。
- 向新角色授予查询参数化视图的权限,但不授予其对基表的访问权限。
- 通过在安全上下文中传递参数,从应用查询参数化视图。
准备工作
您需要一个 Spanner 实例和数据库才能完成本教程。如果您没有实例和数据库,请参阅使用 Google Cloud 控制台创建和查询数据库,以创建实例和 Spanner 数据库。
准备示例数据
在 Google Cloud 控制台中,前往 Spanner 页面。
点击要使用的实例的名称,然后选择要用于本教程的数据库。
在数据库概览页面上的导航菜单中,点击 Spanner Studio。
输入以下 DDL 语句以创建
checked_items表:CREATE TABLE checked_items( bag_id INT64, item_timestamp TIMESTAMP, loc_code STRING(3), scan_type STRING(1), location STRING(MAX), customer_id INT64 ) PRIMARY KEY(bag_id);点击运行。
Spanner 创建表后,输入以下语句以将示例数据插入表中:
INSERT INTO checked_items (bag_id, item_timestamp, loc_code, scan_type, location, customer_id) VALUES (101, '2023-10-26 10:00:00', 'ABC', 'I', 'Warehouse A', 123), (102, '2023-10-26 10:15:30', 'DEF', 'O', 'Loading Dock B', 456), (103, '2023-10-26 10:30:45', 'GHI', 'I', 'Conveyor Belt 1', 789), (104, '2023-10-26 11:00:00', 'JKL', 'O', 'Shipping Area C', 101), (105, '2023-10-26 11:45:15', 'MNO', 'I', 'Sorting Station D', 202), (106, '2023-10-26 12:00:00', 'PQR', 'O', 'Truck Bay E', 303);点击运行。
创建参数化视图
使用 SQL SECURITY DEFINER 创建一个视图,该视图根据 SECURE_CONTEXT() 提供的 app_end_userid 值过滤 checked_items 中的行。此函数会检索从应用安全传递的参数值。
在查询编辑器中,输入以下语句以创建
secure_checked_items视图:CREATE VIEW secure_checked_items SQL SECURITY DEFINER AS (SELECT bag_id, item_timestamp, location FROM checked_items t WHERE customer_id = CAST(SECURE_CONTEXT('app_end_userid'), INT64));点击运行。
设置访问权限
为确保用户只能通过参数化视图访问数据,请创建精细访问权限控制角色,并向该角色授予对视图的 SELECT 权限。确保该角色和 public 系统角色对底层基表都没有权限。
在查询编辑器中,输入以下语句以创建
pv_user角色:CREATE ROLE pv_user;授予对视图的访问权限:
GRANT SELECT ON VIEW secure_checked_items TO ROLE pv_user;点击运行。
不过,如果您需要直接调用 SECURE_CONTEXT() 来调试查询,请为自己授予 spanner_secure_context_reader 角色。您不得将此角色授予不受信任的代理。
使用参数化视图查询数据
应用查询参数化视图时,首先在查询请求的安全上下文中设置参数,然后对视图执行标准 SELECT 查询。该视图使用 SECURE_CONTEXT() 函数根据参数值过滤结果。
以下代码示例演示了如何将 app_end_userid 安全参数设置为 303 并查询 secure_checked_items 视图:
C#
Go
Java
Python
此查询仅返回 checked_items 中 customer_id 为 303 的行:
+--------+---------------------------+-------------+
| bag_id | item_timestamp | location |
+--------+---------------------------+-------------+
| 106 | 2023-10-26 12:00:00+00:00 | Truck Bay E |
+--------+---------------------------+-------------+
1 row.
如果您的应用使用已被授予 pv_user 角色的主账号连接到 Spanner,则任何直接查询 checked_items 表的尝试都会导致权限遭拒错误。