AskTable
sidebar.freeTrial

AskTable 权限控制完全指南:四级权限体系保护企业数据安全

AskTable Team
AskTable Team 2026-03-08

在企业级数据分析场景中,数据安全是头等大事。不同角色的用户应该只能访问自己权限范围内的数据。AskTable 提供了一套完整的权限控制体系,支持库/表/字段/行四级权限控制。

本文将全面讲解 AskTable 的权限控制机制,帮助你构建安全可靠的数据分析系统。


一、为什么需要权限控制?

1. 典型应用场景

场景 1:多租户数据隔离

  • SaaS 平台有多个客户
  • 每个客户只能看到自己的数据
  • 需要在同一个数据库中实现数据隔离

场景 2:分公司数据权限

  • 集团公司有多个分公司
  • 上海分公司只能看上海的数据
  • 北京分公司只能看北京的数据
  • 总部可以看所有数据

场景 3:敏感字段保护

  • 数据库中有敏感字段(手机号、身份证、银行卡)
  • 普通员工不能查看敏感信息
  • 管理员可以查看完整信息

场景 4:环境隔离

  • 生产环境和测试环境的数据分离
  • 测试人员只能访问测试环境
  • 生产人员只能访问生产环境

2. 传统方案的问题

应用层控制

  • ❌ 容易遗漏权限检查
  • ❌ 代码分散,难以维护
  • ❌ 无法应对复杂的 SQL 查询

数据库视图

  • ❌ 视图数量爆炸(角色 × 表)
  • ❌ 无法动态传递用户信息
  • ❌ 维护成本高

AskTable 的解决方案

  • ✅ 统一的权限管理
  • ✅ 动态权限变量
  • ✅ 自动 SQL 改写
  • ✅ 四级权限控制

二、核心概念

1. 数据层级关系

加载图表中...

AskTable 支持在每个层级进行权限控制:

  • 数据源级别:控制能访问哪些数据源
  • Schema 级别:控制能访问哪些数据库
  • 表级别:控制能访问哪些表
  • 字段级别:控制能访问哪些字段
  • 行级别:控制能访问哪些数据行

2. 访问策略(Access Policy)

访问策略定义了某个人能访问(或不能访问)的数据集。

核心属性

  • permission:访问权限(allow 或 deny)
  • name:策略名称
  • dataset_config:数据集配置

策略类型

  • Allow 策略:白名单,只能访问指定的数据
  • Deny 策略:黑名单,不能访问指定的数据

3. 角色(Role)

角色是访问策略的集合,用户通过扮演角色来访问数据。

角色特点

  • 一个角色可以包含多个访问策略
  • 支持动态变量(如 {{user_id}}
  • 可以在查询时传递变量值

三、四级权限控制

1. 数据源级别权限

控制能访问哪些数据源

{
  "permission": "allow",
  "name": "production_only",
  "dataset_config": {
    "datasource_ids": "ds_prod_001"
  }
}

效果

  • 只能访问生产环境数据源
  • 无法访问测试环境数据源

2. Schema 和表级别权限

使用正则表达式匹配

{
  "permission": "allow",
  "name": "public_tables_only",
  "dataset_config": {
    "datasource_ids": "*",
    "regex_patterns": {
      "schemas_regex_pattern": "^public$",
      "tables_regex_pattern": "^(users|orders|products)$"
    }
  }
}

效果

  • 只能访问 public schema
  • 只能访问 users、orders、products 三张表

3. 字段级别权限

隐藏敏感字段

{
  "permission": "deny",
  "name": "hide_sensitive_fields",
  "dataset_config": {
    "datasource_ids": "*",
    "regex_patterns": {
      "fields_regex_pattern": ".*password.*|.*pwd.*|.*phone.*|.*id_card.*"
    }
  }
}

效果

  • 不能访问包含 password、pwd、phone、id_card 的字段
  • AI 生成 SQL 时会自动排除这些字段

4. 行级别权限

过滤数据行

{
  "permission": "allow",
  "name": "regional_data",
  "dataset_config": {
    "datasource_ids": "ds_001",
    "rows_filters": {
      "ds_001": [
        "public.orders.region = {{region}}",
        "public.users.status = 'active'"
      ]
    }
  }
}

效果

  • 只能查询指定区域的订单
  • 只能查询状态为 active 的用户
  • SQL 会自动注入 WHERE 条件

四、动态权限变量

1. 什么是动态变量?

动态变量允许在查询时传递参数,实现更灵活的权限控制。

语法{{variable_name}}

支持的变量类型

  • 用户 ID:{{user_id}}
  • 区域:{{region}}
  • 部门:{{department_id}}
  • 任意自定义变量

2. 使用示例

定义策略

{
  "permission": "allow",
  "name": "user_own_data",
  "dataset_config": {
    "datasource_ids": "ds_001",
    "rows_filters": {
      "ds_001": [
        "public.orders.user_id = {{user_id}}",
        "public.*.created_by = {{user_id}}"
      ]
    }
  }
}

查询时传递变量

from asktable import Asktable

client = Asktable(api_key="your_api_key")

# 查询时传递 user_id
response = client.answers.create(
    datasource_id="ds_001",
    question="查询我的订单",
    role_id="role_employee",
    role_variables={"user_id": "12345"}
)

实际执行的 SQL

SELECT * FROM orders
WHERE user_id = '12345'  -- 自动注入

3. 高级用法

支持的操作符

  • 等于:=
  • 不等于:!=, <>
  • 大于/小于:>, <, >=, <=
  • IN:IN (value1, value2)
  • LIKE:LIKE 'pattern'
  • IS NULL:IS NULL, IS NOT NULL

支持的函数

  • NOW():当前时间
  • 时间计算:NOW() - 1 YEAR, NOW() - 30 DAY

示例

{
  "rows_filters": {
    "ds_001": [
      "public.orders.created_at > NOW() - 30 DAY",
      "public.orders.amount >= 1000",
      "public.orders.status IN ('paid', 'shipped')"
    ]
  }
}

五、实战案例

案例 1:多租户数据隔离

场景:SaaS 平台,每个租户只能看自己的数据

步骤 1:创建访问策略

{
  "permission": "allow",
  "name": "tenant_isolation",
  "dataset_config": {
    "datasource_ids": "ds_saas",
    "rows_filters": {
      "ds_saas": [
        "*.*.tenant_id = {{tenant_id}}"
      ]
    }
  }
}

步骤 2:创建角色

{
  "name": "tenant_user",
  "policies": ["tenant_isolation"]
}

步骤 3:查询时传递租户 ID

response = client.answers.create(
    datasource_id="ds_saas",
    question="查询用户总数",
    role_id="role_tenant_user",
    role_variables={"tenant_id": "tenant_abc"}
)

效果

  • 租户 A 只能看到自己的数据
  • 租户 B 只能看到自己的数据
  • 完全隔离,互不干扰

案例 2:分公司数据权限

场景:集团公司,分公司只能看自己区域的数据

步骤 1:创建区域策略

{
  "permission": "allow",
  "name": "regional_access",
  "dataset_config": {
    "datasource_ids": "ds_erp",
    "rows_filters": {
      "ds_erp": [
        "public.orders.region = {{region}}",
        "public.customers.region = {{region}}",
        "public.employees.region = {{region}}"
      ]
    }
  }
}

步骤 2:创建角色

{
  "name": "regional_manager",
  "policies": ["regional_access"]
}

步骤 3:不同区域的查询

# 上海分公司
response = client.answers.create(
    datasource_id="ds_erp",
    question="查询本月销售额",
    role_id="role_regional_manager",
    role_variables={"region": "上海"}
)

# 北京分公司
response = client.answers.create(
    datasource_id="ds_erp",
    question="查询本月销售额",
    role_id="role_regional_manager",
    role_variables={"region": "北京"}
)

案例 3:敏感字段脱敏

场景:普通员工不能查看手机号、身份证等敏感信息

步骤 1:创建敏感字段拒绝策略

{
  "permission": "deny",
  "name": "hide_pii",
  "dataset_config": {
    "datasource_ids": "*",
    "regex_patterns": {
      "fields_regex_pattern": ".*phone.*|.*mobile.*|.*id_card.*|.*ssn.*|.*credit_card.*"
    }
  }
}

步骤 2:创建普通员工角色

{
  "name": "employee",
  "policies": ["hide_pii"]
}

步骤 3:创建管理员角色(无限制)

{
  "name": "admin",
  "policies": []  // 无限制
}

效果

  • 普通员工查询时,AI 不会选择敏感字段
  • 管理员可以查询所有字段

案例 4:时间范围限制

场景:员工只能查询最近 90 天的数据

步骤 1:创建时间限制策略

{
  "permission": "allow",
  "name": "recent_data_only",
  "dataset_config": {
    "datasource_ids": "ds_001",
    "rows_filters": {
      "ds_001": [
        "*.*.created_at > NOW() - 90 DAY"
      ]
    }
  }
}

效果

  • 所有查询自动限制在最近 90 天
  • 无法查询历史数据

六、权限策略最佳实践

1. 最小权限原则

只授予必要的权限

  • 默认拒绝所有访问
  • 明确授予需要的权限
  • 定期审查权限配置

示例

// 不好的做法:授予所有权限
{
  "permission": "allow",
  "dataset_config": {
    "datasource_ids": "*"
  }
}

// 好的做法:明确指定
{
  "permission": "allow",
  "dataset_config": {
    "datasource_ids": "ds_001",
    "regex_patterns": {
      "tables_regex_pattern": "^(users|orders)$"
    }
  }
}

2. 分层权限设计

建议的权限层次

  1. 基础权限:所有用户都有的权限
  2. 部门权限:按部门划分的权限
  3. 角色权限:按角色划分的权限
  4. 个人权限:特殊用户的权限

3. 使用正则表达式

灵活匹配表名和字段名

{
  "regex_patterns": {
    // 匹配所有以 user_ 开头的表
    "tables_regex_pattern": "^user_.*$",

    // 匹配所有包含 temp 或 test 的表
    "tables_regex_pattern": ".*(temp|test).*",

    // 匹配所有敏感字段
    "fields_regex_pattern": ".*(password|pwd|secret|token|key).*"
  }
}

4. 动态变量命名规范

建议的命名规范

  • 使用小写字母和下划线
  • 语义清晰
  • 避免使用缩写

示例

✅ user_id
✅ department_id
✅ region_code
✅ start_date

❌ uid
❌ did
❌ r
❌ sd

七、权限测试与验证

1. 测试策略

测试清单

  • 测试允许访问的数据
  • 测试拒绝访问的数据
  • 测试动态变量替换
  • 测试边界条件
  • 测试多策略组合

2. 验证方法

方法 1:使用 MCP 测试

from asktable import Asktable

client = Asktable(api_key="your_api_key")

# 测试查询
response = client.sqls.create(
    datasource_id="ds_001",
    question="查询所有用户",
    role_id="role_employee",
    role_variables={"user_id": "12345"}
)

# 查看生成的 SQL
print(response.query.sql)
# 应该包含:WHERE user_id = '12345'

方法 2:直接查看 SQL

在 AskTable 界面中:

  1. 使用"生成 SQL"功能
  2. 查看生成的 SQL 语句
  3. 确认权限条件已正确注入

3. 常见问题排查

问题 1:权限没有生效

检查:

  • 角色是否正确配置
  • 策略是否正确关联到角色
  • 查询时是否传递了 role_id

问题 2:动态变量没有替换

检查:

  • 变量名是否正确(大小写敏感)
  • 是否传递了 role_variables
  • 变量值的类型是否正确

问题 3:权限过于严格

检查:

  • 是否有多个 deny 策略冲突
  • 正则表达式是否过于严格
  • 行级过滤条件是否过于严格

八、高级功能

1. 多策略组合

一个角色可以包含多个策略

{
  "name": "sales_manager",
  "policies": [
    "regional_access",      // 区域限制
    "hide_pii",            // 隐藏敏感信息
    "recent_data_only"     // 时间限制
  ]
}

策略优先级

  • Deny 策略优先于 Allow 策略
  • 多个 Allow 策略取交集
  • 多个 Deny 策略取并集

2. 通配符使用

数据源通配符

{
  "datasource_ids": "*"  // 所有数据源
}

表名通配符

{
  "rows_filters": {
    "ds_001": [
      "*.*.user_id = {{user_id}}"  // 所有表的 user_id 字段
    ]
  }
}

3. 复杂过滤条件

多个条件组合

{
  "rows_filters": {
    "ds_001": [
      "public.orders.user_id = {{user_id}}",
      "public.orders.status IN ('paid', 'shipped')",
      "public.orders.created_at > NOW() - 30 DAY"
    ]
  }
}

注意

  • 多个条件之间是 AND 关系
  • 每个条件独立生效

九、总结

AskTable 的权限控制体系提供了:

核心能力: ✅ 四级权限控制(数据源/Schema/表/字段/行) ✅ 动态权限变量 ✅ 灵活的策略组合 ✅ 自动 SQL 改写

最佳实践: ✅ 遵循最小权限原则 ✅ 使用动态变量实现灵活控制 ✅ 定期审查和测试权限配置 ✅ 文档化权限设计

下一步


相关阅读

技术交流

cta.readyToSimplify

sidebar.noProgrammingNeededsidebar.startFreeTrial

cta.noCreditCard
cta.quickStart
cta.dbSupport