【原理篇】Supabase 的 API Key 工作机制和使用场景
Supabase 的 API Key
跟大多数公网服务一样,Supabase 通过 API Key 来约束客户端对 REST API 的访问。有所不同的是,大多数公网服务的 API Key 都是需要用户保密的,一旦泄露,会导致恶意用户直接操作所使用的服务接口,典型的例子如:ChatGPT。因此一般公网服务的 API key 只能在服务端使用。
Supabase 的服务形式有所不同,他允许开发者直接在 web 或 app 客户端调用接口,大家都知道,API key 配置在客户端上是没有保密性的,尤其 JavaScript 明文直接就可以被任何人看到,因此 Supabase 内置了两个 API Key,以应对该问题:
- Anon Key 
这个 API Key 是可以在 Web 和移动应用客户端使用的 key,不需要担心 key 泄露。顾名思义,这个 key 默认对应的是一个 anon(匿名)用户,匿名用户具有最低的数据访问权,通常不能访问任何数据,因此不必担心 key 泄露后的安全问题。那么问题来了,一个最低权限的 API key 如何给开发者使用来开发应用呢?我会在下文介绍其工作原理。
- Service Role Key 
这个 Key 具有最高的 API 访问权限,用户使用该 Key 可以进行任意操作,因此只能配置到服务端使用,不能泄露。所以 Service Role Key 扮演的是大家常见的 API Key 的角色。
简单来说,Supabase 提供了 2 个 Key,如果是 Web 或者移动应用,直接在客户端调用 Supabase 接口的话,必须使用 Anon key。服务端程序则可以根据场景需要来决定使用 Anon key 还是 Service Role Key。具体使用方法我们在下文详细介绍。
API Key 的验证流程
在介绍验证流程前,我们看一下使用 API Key 调用 Supabase 接口的方法:
可以看到上面 HTTP 请求指定了两个 Header:
- apikey:调用 Supabase 接口所需要的 API Key 
- Authorization:当前会话的用户认证 token 
下图是 Supabase 的验证 API Key 的一般过程:
 
 - 客户端携带 Anon key 和 Anon Token,调用 Login 接口 
- kong 接收到 API 调用请求后,验证 apikey 是否符合要求,这里必须二选一,要么是 anon key,要么是 service role key。验证失败,则直接返回客户端 key 错误。验证通过则将登录请求转发给 Auth 服务。 
- Auth 处理登录请求,并返回登录成功后的用户认证 token。 
- kong 将登录请求的最终结果返回给客户端,此时如果登录成功,客户端会拿到正式的认证 token。 
- 登录成功后,客户端调用 REST 接口访问数据,此时 apikey 仍旧传 anon key,而 Authorization Token 则需要填 Auth 服务返回的 Token。 
- kong 仍旧只验证 apikey,发现是 anon 或者 service role key 则将请求转发给 postgrest 服务。 
- postgrest 解析 Authorization Token,并识别相应的角色和用户信息,根据权限设置来判断当前登录的用户是否有对应用户的数据访问权限,有则继续执行具体的操作,没有则报错。操作执行完后,返回用户需要的数据。 
- kong 将最终结果返回给客户端。 
以上是一轮常规 API 请求的执行流程,当然,用户登录只需要执行一次,直到 Authorization Token 过期,都不需要再次登录。
我们回头看一下上面 API 调用示例中 curl 命令传递的两个参数,会发现 apikey 和 Authorization 传的都是 Anon Key。如果此时不调用登录接口,直接调用 REST API 操作数据,会发生什么事情呢?我们沿着 API 调用路径来看一下执行流程:
- 首先,kong 会校验 apikey 认为该 API 调用是合法的,将请求转发给 postgrest 服务。 
- postgrest 服务解析 Authorization Token,发现解析出来的 role 是 anon,此时该 api 是否能正常执行,取决于 anon role 是否有相应的权限。为什么 postgrest 会解析 role,以及如何解析 role 的,请参考《SupaBase权限模型part2》 
- 如果用户关闭了 RLS,是不会校验任何权限的,此时接口会正常执行。 
- 如果用户开启了 RLS,默认 anon 用户没有任何数据的访问权限,以该接口为例(查询 mytable 表的 id 字段),会返回空列表。 
- 如果开发者期望 anon 用户也能读取某些数据,就需要为 anon 设置相应的权限。比较典型的场景,比如微博,用户没有登录也是可以看到其他用户发的微博信息的,这类场景就需要为 anon 用户开启数据访问权。 
如果用户传给 apikey 和 Authorization 的是 service role key,又会发生什么呢?
- kong 仍旧只校验 apikey 并放行 
- postgrest 提取出来的 role 是 service_role,该角色拥有最高权限,因此不论用户是否开启了 RLS 以及设置了何种规则,都会被无视。 
- service role 拥有所有数据的访问权。 
如何正确使用 Anon key 和 ServiceRole key
可以参照如下一些基本原则:
- 客户端只能配置 Anon key。需要配合 RLS 策略来管理数据访问权限。 
- 服务端可以配置 Anon key,也可以配置 ServiceRole key。 
- ServiceRole key 会绕过所有 RLS 管控策略,因此使用 ServiceRole key 开发应用时,数据访问权限需要在程序中实现,不能依赖 Supabase 的 RLS 策略。 
- 一些特定的 API 只能使用 ServiceRole key 访问,比如 postgres-meta 的 API。 
版权声明: 本文为 InfoQ 作者【张文平】的原创文章。
原文链接:【http://xie.infoq.cn/article/526537e72871894e18277da83】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。











 
    
评论