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

Next.js集成Supabase/SSR与行级安全(RLS)配置问题求助

解决Next.js + @supabase/ssr 行级安全(RLS)规则不生效问题

核心原因是新版@supabase/ssr为无状态设计,服务器端不会自动保留用户会话,必须在每次请求中主动传递认证信息,才能让RLS规则中的auth.uid()获取到当前用户ID。以下是完整配置步骤:

1. 正确初始化Supabase SSR客户端

在项目中创建lib/supabase.ts,基于Next.js的cookies()实现会话传递:

import { createServerClient, type CookieOptions } from '@supabase/ssr'
import { cookies } from 'next/headers'

export const createSupabaseServerClient = async () => {
  const cookieStore = cookies()

  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        get(name: string) {
          return cookieStore.get(name)?.value
        },
        set(name: string, value: string, options: CookieOptions) {
          try {
            cookieStore.set({ name, value, ...options })
          } catch (error) {
            // Server Component中无法设置Cookie,仅在登录/登出等需要修改会话的场景(Route Handler/Client Component)触发
          }
        },
        remove(name: string, options: CookieOptions) {
          try {
            cookieStore.set({ name, value: '', ...options })
          } catch (error) {
            // 同上
          }
        },
      },
    }
  )
}

2. 在Server Component/Route Handler中传递会话

Server Component示例

必须先获取用户会话,确保认证信息被传递到Supabase服务端:

import { createSupabaseServerClient } from '@/lib/supabase'

export default async function UserProfile() {
  const supabase = await createSupabaseServerClient()
  
  // 触发会话验证,让RLS能获取到用户ID
  const { data: { user } } = await supabase.auth.getUser()
  
  if (!user) {
    return <div>请先登录</div>
  }

  // 此时RLS规则`user_id = auth.uid()`会自动生效,无需手动过滤
  const { data: userPosts } = await supabase.from('posts').select('*')

  return (
    <div>
      <h1>你的帖子</h1>
      {userPosts?.map(post => (
        <div key={post.id}>{post.title}</div>
      ))}
    </div>
  )
}

Route Handler示例(API路由)

import { createSupabaseServerClient } from '@/lib/supabase'
import { NextResponse } from 'next/server'

export async function GET() {
  const supabase = await createSupabaseServerClient()
  
  const { data: { user } } = await supabase.auth.getUser()
  
  if (!user) {
    return NextResponse.json({ error: '未授权' }, { status: 401 })
  }

  const { data: userPosts } = await supabase.from('posts').select('*')

  return NextResponse.json(userPosts)
}

3. 验证RLS规则配置

确保数据表满足以下条件:

  1. 已在Supabase控制台开启RLS
  2. 添加正确的RLS策略(以posts表为例):
-- 允许用户查看自己的帖子
CREATE POLICY "用户仅能查询自身条目" ON posts
FOR SELECT USING (user_id = auth.uid());

-- 允许用户创建属于自己的帖子
CREATE POLICY "用户仅能插入自身条目" ON posts
FOR INSERT WITH CHECK (user_id = auth.uid());

4. 常见问题排查

  • 确认用户已登录:通过客户端supabase.auth.getUser()验证用户会话存在
  • 检查字段类型:user_id必须为UUID类型,与auth.uid()返回值类型一致
  • 避免使用service_role密钥:该密钥会绕过RLS,仅在后台管理场景使用
  • 验证策略状态:在Supabase控制台确认RLS策略已启用并覆盖对应操作(SELECT/INSERT等)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 11:24:52