如何从React Native应用调用Amplify保护的Next.js REST接口
问题解决方案
核心问题在于移动端请求未正确携带认证令牌,同时Next.js服务端未从请求头解析令牌,以下是分步解决方法:
一、移动端自动携带认证令牌到请求头
Amplify的API模块不会默认给自定义端点附加认证信息,可通过两种方式实现令牌携带:
方法1:配置Amplify自动附加令牌
修改移动端Amplify配置,为API端点指定认证类型,让Amplify自动注入令牌:
Amplify.configure({ ...awsconfig, API: { endpoints: [ { name: 'MyApi', endpoint: 'http://NextIP:NextPort/api/', authenticationType: 'AMAZON_COGNITO_USER_POOLS' // 新增该行 }, ], }, })
配置后,Amplify会自动将当前登录用户的Access Token以Bearer <token>格式加入请求的Authorization头。
方法2:手动获取令牌并添加
若自动配置不生效,可手动获取令牌后写入请求头:
async function getData() { const apiName = 'MyApi' const path = '/version' // 获取当前用户会话令牌 const session = await Auth.currentSession() const accessToken = session.getAccessToken().getJwtToken() const myInit = { headers: { Authorization: `Bearer ${accessToken}` } } return API.get(apiName, path, myInit) }
二、Next.js服务端解析Bearer令牌完成认证
原代码使用withSSRContext({req})默认从Cookie读取认证信息,但移动端请求携带的是Authorization头,需修改服务端逻辑解析令牌:
import type { NextApiRequest, NextApiResponse } from 'next' import { Amplify, Auth } from 'aws-amplify' import awsExports from '../../aws-exports' // 确保路径与项目匹配 // Lambda@Edge环境需在函数内部初始化Amplify,避免复用环境导致的配置问题 Amplify.configure({ ...awsExports, ssr: true }) export default async function handler( req: NextApiRequest, res: NextApiResponse<any>, ) { try { // 解析Authorization头中的Bearer令牌 const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { throw new Error('无效的认证头'); } const token = authHeader.split(' ')[1]; // 验证令牌并获取用户信息 const user = await Auth.currentAuthenticatedUser({ bypassCache: true }); return res.status(200).json({ version: '1.0.0', user: user.username, }) } catch (err) { console.log(err) return res.status(401).json({ // 返回401更符合HTTP规范 message: '未认证', }) } }
三、RTK Query的认证配置
若使用RTK Query发起请求,需在baseQuery中动态添加认证头:
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' import { Auth } from 'aws-amplify' export const apiSlice = createApi({ reducerPath: 'api', baseQuery: fetchBaseQuery({ baseUrl: 'http://NextIP:NextPort/api/', prepareHeaders: async (headers) => { const session = await Auth.currentSession() const token = session.getAccessToken().getJwtToken() if (token) { headers.set('Authorization', `Bearer ${token}`) } return headers }, }), endpoints: (builder) => ({ getApiVersion: builder.query({ query: () => '/version', }), }), }) export const { useGetApiVersionQuery } = apiSlice
额外注意事项
- 确保移动端与Next.js端的Amplify配置(
aws-exports)属于同一环境,用户池ID、客户端ID等参数完全一致; - Lambda@Edge的CORS配置需允许
Authorization头,响应头需包含Access-Control-Allow-Headers: Authorization; - 移动端无需使用Cookie传递认证信息,Bearer头是更适合移动端的认证方式。
内容的提问来源于stack exchange,提问作者Trudgedy
相关产品推荐
相关产品推荐

