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

在Next.js API Routes中使用已认证用户执行GraphQL Mutation的问题

在Next.js API Routes中使用已认证用户执行GraphQL Mutation的问题

嘿,这个问题我之前帮朋友排查过,其实核心原因很简单——你在服务器端的API路由里直接用默认的generateClient(),但它默认是从客户端本地存储取用户认证信息的,而API Routes跑在服务器上,根本访问不到浏览器里的用户会话数据,所以才会抛出NoSignedUser错误。

给你两个实用的解决思路,都是我实际用过的:

方法一:手动传递认证令牌,在服务器端配置客户端

这个是最贴合Amplify生态的方案,分两步走:

1. 客户端调用API路由时携带认证令牌

在前端的客户端组件里,先拿到当前登录用户的JWT令牌,然后在请求API路由时把它放在请求头里:

// 客户端组件中的请求代码
import { getCurrentUser } from 'aws-amplify/auth';

const executeMutationViaAPI = async (mutationData) => {
  try {
    // 获取当前登录用户的令牌
    const user = await getCurrentUser();
    const authToken = user.signInUserSession.idToken.jwtToken;

    // 调用API路由,携带令牌和mutation参数
    const response = await fetch('/api/your-mutation-route', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${authToken}`
      },
      body: JSON.stringify(mutationData)
    });

    return await response.json();
  } catch (error) {
    console.error('调用API路由失败:', error);
  }
};

2. API路由中用令牌配置Amplify客户端

在API路由文件里,先从请求头取出令牌,然后重新配置Amplify,再生成带认证的客户端:

import { generateClient } from 'aws-amplify/api';
import { Amplify } from 'aws-amplify';
import amplifyConfig from '../../amplifyconfiguration.json'; // 你的Amplify配置文件路径

export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ message: '只支持POST方法' });
  }

  // 从请求头提取认证令牌
  const authToken = req.headers.authorization?.replace('Bearer ', '');
  if (!authToken) {
    return res.status(401).json({ message: '请先登录' });
  }

  // 重新配置Amplify,传入服务器端可用的认证信息
  Amplify.configure({
    ...amplifyConfig,
    Auth: {
      credentials: () => ({
        sessionToken: authToken,
        // 其他可选字段,如果用IAM认证需要填accessKeyId等,否则留空即可
        accessKeyId: '',
        secretAccessKey: '',
        expiration: new Date(Date.now() + 3600000) // 令牌过期时间,可根据实际调整
      })
    }
  });

  // 用配置好的Amplify生成客户端
  const graphqlClient = generateClient();

  try {
    const mutationParams = req.body;
    // 执行你的GraphQL Mutation
    const result = await graphqlClient.graphql({
      query: `
        mutation YourMutationName($input: YourMutationInput!) {
          yourMutationField(input: $input) {
            // 你要返回的字段
            id
            name
          }
        }
      `,
      variables: { input: mutationParams }
    });

    res.status(200).json(result.data);
  } catch (error) {
    console.error('Mutation执行出错:', error);
    res.status(500).json({ message: 'Mutation执行失败', error: error.message });
  }
}

方法二:直接用AWS SDK签名请求(适合熟悉AWS签名的场景)

如果你的Amplify用的是Cognito认证,也可以直接用@aws-sdk/client-appsync来调用API,手动用令牌签名请求,不过这个方法比上面的要繁琐一些,适合对AWS SDK比较熟悉的情况,核心思路是用AppSyncClient,并在请求配置里传入authorization: { type: 'AMAZON_COGNITO_USER_POOLS', jwtToken: authToken }。

额外注意点

  • 确保你的amplifyconfiguration.json路径正确,API路由是在pages/api或者app/api下,所以路径要根据项目结构调整。
  • 服务器端每次请求都会重新配置Amplify,不会影响全局状态,因为API Routes是无状态的,每次请求都是独立的。
  • 可以在API路由里加一步令牌验证,比如调用Cognito的GetUser接口来确认令牌有效,避免无效请求。

备注:内容来源于stack exchange,提问作者Besart

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 16:08:03