# 数据访问管理

Typesense 主要通过 RESTful HTTP API 来读写数据,对这些 API 的访问由 API 密钥控制。

GET /health 端点外,所有 API 端点都需要通过 X-TYPESENSE-API-KEY HTTP 头或 ?x-typesense-api-key 查询参数提供 API 密钥。

本文将讨论如何创建 API 密钥,并限制它们可以访问的 API 端点和/或数据。

# 引导 API 密钥

启动 Typesense 集群时,您需要使用 api-key 服务器配置参数 提供一个引导密钥。

该密钥对所有端点和数据拥有管理员权限,不应在常规操作中使用。您应该使用该密钥通过 /keys API 端点 创建另一个管理员 API 密钥,然后将其用于日常操作。

这样,您就可以根据需要轮换/撤销管理员密钥。

TIP

在 Typesense Cloud 中,我们会透明地为您管理引导 API 密钥。

当您在集群仪表板中点击"生成 API 密钥"按钮时,我们会使用引导 API 密钥通过 /keys 端点生成一个管理员 API 密钥和一个仅搜索 API 密钥,并将其提供给您。

# 限制对 API 端点的访问

当您创建 API 密钥时,可以使用 actions 参数来控制该密钥可以访问哪些 API 端点。

请看以下示例密钥配置:

{
  "actions": ["documents:search"],
  "collections": ["*"],
  ...
}

此配置将允许该 API 密钥仅能使用搜索 API 端点来搜索文档。

了解更多关于所有可用的 actions

# 限制对集合的访问

当您创建 API 密钥时,可以使用 collections 参数来控制该密钥可以访问哪些特定集合。

请看以下示例密钥配置:

{
  "actions": ["*"],
  "collections": ["contacts_.*"],
  ...
}

此配置将允许该 API 密钥仅能访问以 contacts_ 开头的集合。

您可以使用任何正则表达式或集合名称列表来指定该密钥可以访问哪些集合。

# 限制对集合内文档的访问权限

假设您正在构建一个书签服务,每个用户都可以创建自己的书签。 您可以将所有用户的书签放在同一个集合中,并使用范围限定搜索API密钥来确保用户只能搜索自己的书签。

范围限定搜索API密钥的核心概念是:您可以在API密钥中加密嵌入一个filter_by子句,例如filter_by: belongs_to_user_id:=CurrentUserId。 当您使用该API密钥进行搜索时,Typesense会自动应用这个过滤器。用户无法覆盖嵌入在范围限定API密钥中的过滤器。

这实际上意味着该API密钥只能访问具有belongs_to_user_id: CurrentUserId属性的文档。

了解更多关于范围限定搜索API密钥的信息

# 限制文档中字段的访问权限

假设您正在构建一个客户查询门户,客服人员可以查看客户信息,但您希望某些信息(如账单地址)仅对管理员组可见,而非所有人员都能查看。

您可以在include_fieldsexclude_fields参数中嵌入一个限定搜索API密钥,例如exclude_fields: billing_address

当客服人员登录时,您可以向后端发起API调用,创建/获取一个对该集合具有搜索权限的只读搜索API密钥,然后根据您认证系统中该人员的角色,创建一个嵌入了include_fieldsexclude_fields参数的限定搜索API密钥,将此限定API密钥发送至前端,最后由前端向Typesense发起API调用。

了解更多关于限定搜索API密钥的信息

# 在前端暴露 API 密钥

Typesense 的设计允许搜索请求直接从用户的浏览器/移动应用发送到您的 Typesense 集群,而无需通过后端服务器代理这些搜索调用。

因此您可以在前端暴露 仅搜索 API 密钥,因为该密钥授予用户的访问权限与通过您的搜索 UI 获得的权限相同。

唯一不建议在前端暴露仅搜索 API 密钥的情况是当您使用 限定范围搜索 API 密钥时, 该密钥嵌入了过滤器或其他搜索参数以实现以下目的:

这是因为暴露用于生成限定范围搜索 API 密钥的父级仅搜索 API 密钥,将允许用户执行无范围限制的搜索,而这并非您希望发生的情况。

WARNING

绝对不要在前端应用中暴露您的管理员 API 密钥引导 API 密钥,因为任何获取这些密钥的人都能向您的集合中写入数据。

# 密钥轮换

当你通过 /keys API 端点 创建 API 密钥时,可以设置 expires_at 值来指定该密钥有效的 Unix 时间戳。

良好的安全实践是定期创建具有短期有效期的 API 密钥,以降低密钥泄露的风险。

例如,与其在应用中硬编码 API 密钥,你可以让前端调用后端 API 来获取最新的 API 密钥。如果密钥已过期,后端可以创建另一个具有短期有效期的密钥并返回给前端使用。

或者,如果你的应用需要用户登录,可以在用户登录时在后端为每个用户单独创建搜索 API 密钥,根据需要生成一个限定范围的搜索 API 密钥,并将其发送给前端使用。

TIP

特别重要的是,不要在本机移动应用中硬编码 API 密钥甚至 Typesense 主机名,因为这样会导致难以动态轮换密钥。

因此,你应当在后端设置一个 API 端点,在应用加载时或用户登录时,可以从中获取 Typesense 集群主机名和 API 密钥。

这种方式可以避免潜在的应用商店漫长审核周期,以及不得不继续支持使用旧 API 密钥的应用旧版本。

# 防爬保护

如果您的搜索栏是公开的,并且希望防止数据被爬虫抓取,您可以限制单个搜索查询能够获取的结果总数。这能有效阻止爬虫获取您的完整数据集。

您需要生成一个限定范围搜索API密钥, 在其中嵌入limit_hits参数, 然后在前端应用中使用该限定范围搜索密钥。

如果使用multi_search功能,还需要在限定范围搜索API密钥中嵌入limit_multi_searches参数,以限制单个multi_search请求中可以发送的搜索次数。

# DDOS防护

众所周知,在没有大量资源的情况下很难抵御DDOS攻击。 因此,如果您需要防范DDOS攻击,我们建议将每个Typesense节点主机名配置在Cloudflare DNS端点后方(开启Proxy设置并将SSL模式设为Full), 然后在Typesense客户端配置中使用Cloudflare主机名。

例如,对于一个3节点集群,您可以设置以下代理连接:

ts-ha.yourdomain.com -> xxx.a1.typesense.net
ts1.yourdomain.com -> xxx-1.a1.typesense.net
ts2.yourdomain.com -> xxx-2.a1.typesense.net
ts3.yourdomain.com -> xxx-3.a1.typesense.net

其中xxx*.a1.typesense.net是您Typesense集群各节点的原始主机名。

之后在实例化客户端库或进行API调用时使用ts*.yourdomain.com主机名,这样请求将通过Cloudflare路由,任何DDOS攻击在到达您的原始Typesense节点之前就能被Cloudflare处理。