You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用自定义JWT及RLS时Supabase Realtime无事件触发的问题求助

自定义JWT结合RLS时Supabase实时数据无法触发问题

我在使用行级安全(RLS)和自定义JWT时,无法从Supabase数据库获取实时数据。普通查询数据库一切符合预期,但使用Realtime功能监听变更时,完全没有事件触发。

Astro框架代码实现

import { createClient } from "@supabase/supabase-js";

const supabase = await createClient(import.meta.env.PUBLIC_SUPABASE_URL, import.meta.env.PUBLIC_SUPABASE_KEY, {
        global: {
            headers: {
                Authorization: `Bearer ${jwt}`,
            },
        },
    });

supabase.from('notes').select().then(({data, error}) => {
    console.log(data, error) // 这里正常工作,控制台能输出我的notes数据
})

// 不确定这两行是否必要,查了大量资料后添加
supabase.realtime.setAuth(jwt)
supabase.realtime.accessToken = jwt

// 问题核心:当notes表发生更新时,控制台无任何输出
supabase
    .channel('notes')
    .on('postgres_changes', { event: '*', schema: '*', table: 'notes' }, payload => {
        console.log("检测到notes数据库变更:", payload) // 这条日志从未执行
    })
    .subscribe()

notes表RLS规则

(((current_setting('request.jwt.claims'::text, true))::json #>> '{email}'::text[]) IS NOT NULL)

疑问

这种失败看起来像是JWT不包含email字段,但为什么普通查询能正常工作?

自定义JWT生成代码(基于Jose库)

const signingSecret = import.meta.env.SUPABASE_JWT_SECRET;
if (signingSecret) {
    session.supabaseAccessToken = await new jose.SignJWT({ email: user.email, role: "authenticated" })
    .setProtectedHeader({ alg: 'HS256' })
    .setAudience("authenticated")
    .setExpirationTime(Math.floor(new Date(session.expires).getTime() / 1000))
    .setSubject(user.id)
    .sign(new TextEncoder().encode(signingSecret))
}

测试结果

  • 使用service_role用户可以正常看到实时更新;
  • 使用anon_user用户无法看到实时更新。

补充信息

开发者工具网络标签显示WebSocket连接正常(能看到心跳和同步事件),但没有postgres事件传输。由于对数据库不熟悉,难以调试RLS策略,也没有便捷方式记录RLS策略失败的场景。

内容的提问来源于stack exchange,提问作者Andrew Bloyce

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 10:56:25