在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
相关产品推荐
相关产品推荐

