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

如何解决Supabase中执行.insert()时触发的RLS策略403错误?

习惯追踪应用Supabase RLS插入403错误排查

问题背景

开发习惯追踪应用时,采用Supabase PostgreSQL作为数据库,为habit表配置了行级安全(RLS)策略,但点击「创建习惯」按钮触发数据插入时,Supabase API返回403错误,提示:

new row violates row-level security policy for table "habit"

该问题已持续3天,以下是相关前端代码及RLS配置信息:

前端代码

export default function AddHabit({token}) {

    const [color, setColor] = useState('rgba(255, 255, 255, 1)');
    let navigate = useNavigate();
    const [formData, updateFormData] = useState({
        name: "",
        streak: 0,
        color_hex: color,
        dates_completed: [""],
        times_per_day: "",
        days_goal: "",
        user_id: token.user.id
    })
    
    const handleChange = (event) => {
        updateFormData((prevFormData) => {
            return {
                ...prevFormData,
                [event.target.name]:event.target.value
            }
        })
    }

    async function handleSubmit(e) {
        e.preventDefault();

        try {
            
            const { data, error } = await supabase
            .from('habit')
            .insert([
                    {
                        name: formData.name,
                        streak: formData.streak,
                        color_hex: formData.color_hex,
                        dates_completed: formData.dates_completed,
                        times_per_day: formData.times_per_day,
                        days_goal: formData.days_goal,
                        user_id: formData.user_id
                    }
            ]).select('*')
            console.log(formData);
            if (error) {
                console.log("Error found: ", error);
            };
            console.log(data);
            navigate("/home");

        } catch (error) {
            alert(error);
        }
    } 

    return (
        <div className="flex flex-col items-center">
            <h1 className="text-4xl py-8 text-white font-bold">Add a Habit here!</h1>

            <div className="grid grid-cols-2 divide-x-2 divide-zinc-500">
                <div className="flex flex-col items-center space-y-4 pr-16">
                    <h2>Create</h2>
                    <div className="flex flex-col space-y-2">
                        <input type="text" name="name" onChange={handleChange} placeholder="Habit Name?" required className="input input-bordered input-white "/>
                        <input type="number" max={24} name="times_per_day" onChange={handleChange} placeholder="Times per day?" required className="input input-bordered input-white"/>
                        <input type="number" max={1000} name="days_goal" onChange={handleChange} placeholder="Goal (How many days)?" required className="input input-bordered input-white"/>
                    </div>

                    <ColorPicker id="color" value={color} onChange={setColor} hidePresets={true} hideControls={true} hideOpacity={true} hideInputs={false} />
                </div>
                <div className="flex flex-col items-center space-y-4 p-4">
                    <h2>Preview</h2>
                    <HabitTile  name={formData.name} hex={color} times_per_day={formData.times_per_day} days_goal={formData.days_goal}/>
                </div>
            </div>
            <button className="btn btn-primary" onClick={handleSubmit} >Add this Habit</button>
        </div>
    )
}

RLS策略配置

habit表的RLS配置信息(基于截图整理):

  • 表RLS状态:已启用
  • INSERT策略:
    • 策略名称:允许认证用户插入自己的习惯
    • 应用角色:authenticated
    • 策略条件:user_id = auth.uid()

排查与解决方案

1. 验证用户ID一致性

  • 在handleSubmit函数中添加日志,打印token.user.id,同时在Supabase控制台SQL编辑器执行select auth.uid();,确认两者是否完全一致,避免因ID格式或值错误导致策略验证失败
  • 检查formData.user_id在提交时是否被正确赋值,避免状态更新延迟导致值为空

2. 完善RLS策略条件

  • 确保INSERT策略同时配置了USING和WITH CHECK子句,且均为user_id = auth.uid()(WITH CHECK用于验证插入的行是否符合策略,仅配置USING可能无法覆盖插入场景)
  • 确认策略已正确应用到authenticated角色,没有遗漏角色配置

3. 确认客户端认证状态

  • 在handleSubmit开头添加认证状态检查:
    const { data: { user }, error: authError } = await supabase.auth.getUser();
    if (authError || !user) {
      console.log("用户未认证");
      return;
    }
    
    确保Supabase客户端已正确认证,用户ID与token.user.id匹配

4. 匹配字段数据类型

  • 数据库中times_per_day和days_goal若为数值类型,前端提交时需将输入的字符串转为数字:
    times_per_day: parseInt(formData.times_per_day),
    days_goal: parseInt(formData.days_goal)
    
  • 确认dates_completed字段在数据库中的类型(如text[]或jsonb)与前端传入的数组格式匹配,避免类型不匹配触发策略验证失败

5. 手动测试策略有效性

在Supabase控制台SQL编辑器执行以下语句,模拟前端插入请求:

INSERT INTO habit (name, streak, color_hex, dates_completed, times_per_day, days_goal, user_id)
VALUES ('测试习惯', 0, '#ffffff', '{}', 1, 30, auth.uid());
  • 若执行成功,说明策略本身无问题,问题出在前端数据传递或认证状态
  • 若执行失败,需重新调整RLS策略的条件或权限配置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 22:14:55