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

如何在Next.js API路由中实现Supabase认证查询?

解决Supabase服务器端JWT认证与RLS适配问题

问题核心

你遇到的问题主要出在JWT的处理方式和createServerSupabaseClient的用法上:

  1. 传递给supabase.auth.getUser()的是带Bearer 前缀的完整请求头,而非纯JWT字符串;
  2. 使用createServerSupabaseClient时无需手动传入JWT,该工具会自动解析请求中的认证信息;
  3. 缺乏关键的认证错误处理,导致用户未认证时无法返回正确状态。

修正后的服务器端代码

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse<Data | string>
) {
  try {
    const word = req.body;
    // 创建服务器端Supabase客户端,自动从请求中提取认证信息
    const supabase = createServerSupabaseClient({ req, res });

    // 获取当前认证用户,无需手动传递JWT
    const { data: { user }, error: authError } = await supabase.auth.getUser();

    // 处理未认证或认证失败的情况
    if (authError || !user) {
      return res.status(401).send("Unauthorized");
    }

    // 检查当前用户名下是否已存在该单词(匹配RLS规则)
    const { count, error: countError } = await supabase
      .from("words")
      .select("name", { head: true, count: "exact" })
      .eq("name", word)
      .eq("user_id", user.id);

    if (countError) throw countError;

    if (count) {
      return res.status(409).send("Word already saved");
    }

    // 插入数据并关联当前用户ID
    const { data, error: insertError } = await supabase
      .from("words")
      .insert({ name: word, user_id: user.id });

    if (insertError) throw insertError;

    res.status(200).send("OK");
  } catch (err) {
    console.error(err);
    res.status(500).send("Something went wrong!");
  }
}

关键改动说明

  • 自动认证处理:createServerSupabaseClient会自动识别请求中的Authorization头或Supabase认证Cookie,无需手动提取JWT;
  • 正确获取用户:调用supabase.auth.getUser()无需参数,直接返回当前认证用户,同时增加认证失败的判断,及时返回401未授权状态;
  • 匹配RLS规则:查询单词时添加user_id过滤条件,确保只检查当前用户的数据,和你设置的行级安全规则对齐;
  • 完善错误捕获:为每个数据库操作添加错误处理,避免未捕获异常导致的500错误。

客户端代码优化

客户端无需将JWT作为apiKey传递,apiKey应使用项目的公开匿名密钥:

const session = await supabase.auth.getSession();
const jwt = session.data.session?.access_token;
try {
  const response = await fetch(`/api/word/${route}`, {
    method,
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${jwt}`,
      apiKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
    },
    body: JSON.stringify(word),
  });
} catch (err) {
  console.error("Request failed:", err);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 23:42:28