写点什么

【原理篇】Supabase 权限模型 Part1

作者:张文平
  • 2023-09-04
    湖北
  • 本文字数:2002 字

    阅读完需:约 7 分钟

【原理篇】Supabase 权限模型 Part1

在任何系统中,数据安全、访问控制等问题都至关重要,本篇我们介绍一下 Supabase 的权限模型。

权限问题

在一定程度上,我们可以认为 BaaS 是直接将数据和接口暴露给了最终用户(区别于只把数据和接口暴露给开发者),使用 BAAS 开发的应用的工作模式类似下面这种:

传统的服务接口的使用方式:

传统的开发方式,我们会开发一个 SERVER 程序负责跟后端其他服务接口和数据打交道,这个 server 运行在服务器端,可以很好的隔离 app 对接口和数据的非法访问,各种鉴权处理都是在 SERVER 端完成的。以微信为例,当个人用户登录微信后能看到哪些信息、不能看到哪些信息,是在 SERVER 端处理的。

当我们使用 BAAS 开发应用时,开发者不再需要开发 SERVER 程序,app 直接调用 BAAS 提供的各种服务,那么 BAAS 就需要提供很好的机制来让开发者能开发出具备相同鉴权能力的应用。

当开发者不再开发 SERVER 后,尤其是像 web 这种可以认为所有源代码都是公开的应用,用户是可以看到 app 的所有代码和密钥之类的信息的,此时 BAAS 的服务将面临哪些问题需要解决呢?

从场景上来看

- BAAS 需要区分授权 API 调用和匿名 API 调用

所谓授权 API 调用是指服务端能识别出该 API 调用者的身份;反之就是匿名调用,也就是没有提供任何凭据的 API 调用。通常大多数服务商是禁止匿名调用的,授权方式通常是提供一个 API KEY。

这里面临的挑战是:由于没有 SERVER 这个中间层,API KEY 只能配置到 APP 端,此时这个 API KEY 基本上可以认为是公开的(尤其 web app),任何人都可以看到。一个任何人都可以拿到的 API KEY 如何进行安全的鉴权,这个 API KEY 的工作机制该如何设计?

- BAAS 需要区分已登录用户和未登录用户的 API 调用

未登录用户的典型场景就是用户注册、登录、获取图形验证码等等。

这里有一个细微的差异需要考虑:匿名 API 调用和未登录用户的 API 调用。这里的匿名是指为提供 API KEY 的 API 调用。BAAS 需要支持未登录的用户调用注册等接口,但是是否支持匿名 API 调用可以根据需要来调整。

从数据访问角度来看

- 访问 public 数据

public 数据是否允许匿名 API 访问,是否允许未登录用户访问?如何设计鉴权?

- 访问私有数据(自己的或者别人的)

如何保证私有数据只有具备合法权限的用户才能访问到?

- BAAS 服务间数据互访问(BAAS 是由一系列服务组合起来工作的,如数据库 API、存储 API、用户 API)

比如提供用户注册、登录等功能的 auth 服务需要读写 user 表。如何在保证 auth 服务能正常读写 user 表的同时,确保调用 auth 接口的用户不会任意篡改 user 表?

BAAS 服务要提供能满足真实需要的服务能力,必需提供良好的鉴权机制,并开放给开发者使用。

Supabase 当前解决方案

API 鉴权

Supabase 给 API 调用分了两种 key:anon key、service key

  • anon key:是公开的 key,给 app 使用,所有人可以拿到。所以 anon key 的权限是受限的。

  • service key:使用 service key 调用 api 可以做任何事情,不受限制。因此 service key 只能配置给 BAAS 内部服务使用,这些服务是服务商自己开发的,因此受授信的。

用户数据访问鉴权

Supabase 主要依赖 PostGREST 基于 pg 的 RLS(Row level security)的数据访问控制能力实现数据访问鉴权。参考《postgrest 体验》。

为了配合 PostgREST,Supabase 内置了 3 种 user role:anon、authenticated、service_role。

  • anon 是用户未登录时使用的 role。

  • authenticated 是用户登录后进行数据操作时使用的 role。

  • service_role 是供其他服务使用的 role,可以绕过 RLS(感觉不是程序实现的,需要在创建这个 role 时设置为 BYPASSRLS,从而是的 RLS 对该 role 不起作用)。

上面的 anon 和 service_role 和 anon key、service key 似乎可以相互呼应。

问题: key 和 role 之间怎么呼应的?

postgrest 检查 role 的方式是从 jwt 的载荷中获取的,kong 中配置的 anon key 以及 service key 就是使用 anon 和 service_role 两个载荷创建的 jwt token。需要使用 jsonwebtoken.io 之类的工具加下类似下面的载荷来生成:

# anon Payload:  {   "iss": "Supabase",   "iat": 1603968834,   "exp": 2550653634,   "aud": "",   "sub": "",   "role": "anon"  }  # service_role Payload:  {   "iss": "Supabase",   "iat": 1603968834,   "exp": 2550653634,   "aud": "",   "sub": "",   "role": "service_role"  }
复制代码

JWTs in Supabase

  1. anon key: This key is used to bypass the Supabase API gateway and can be used in your client-side code.

  2. service role key: This key has super admin rights and can bypass your Row Level Security. Do not put it in your client-side code. Keep it private.

  3. user specific jwts: These are tokens we issue to users who log into your project/service/website. It's the modern equivalent of a session token, and can be used by a user to access content or permissions specific to them.

下一篇我们会详细介绍 postgrest 的 anon、authenticated 等角色的工作机制。

发布于: 刚刚阅读数: 4
用户头像

张文平

关注

Supabase先行者 2020-08-24 加入

还未添加个人简介

评论

发布
暂无评论
【原理篇】Supabase 权限模型 Part1_Serverless_张文平_InfoQ写作社区