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

Next.js 14中React Native移动端应用的API授权方案咨询

双策略适配方案(Web Session + 移动端JWT)

你的思路完全可行,NextAuth支持灵活的认证策略配置,可以同时满足Web端的Session/Cookie需求和移动端的JWT授权。以下是具体实现步骤:

1. 配置NextAuth区分客户端类型

在app/api/auth/[...nextauth]/route.js中,通过请求头识别客户端类型,分别返回对应的认证凭证:

import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import jwt from "jsonwebtoken";

const SECRET = process.env.NEXTAUTH_SECRET || "your-secret-key";

export const authOptions = {
  providers: [
    CredentialsProvider({
      async authorize(credentials) {
        // 替换为你的用户校验逻辑(如查询数据库)
        const user = { id: "1", name: "Test User", email: "test@example.com" };
        if (user) return user;
        return null;
      },
    }),
  ],
  session: { strategy: "jwt" },
  callbacks: {
    async jwt({ token, user }) {
      const isMobile = req.headers.get("X-Client-Type") === "mobile";
      // 为移动端生成专用JWT
      if (user && isMobile) {
        const mobileToken = jwt.sign({ userId: user.id }, SECRET, { expiresIn: "7d" });
        token.mobileToken = mobileToken;
      }
      return token;
    },
    async session({ session, token }) {
      const isMobile = req.headers.get("X-Client-Type") === "mobile";
      // 给移动端返回JWT,Web端返回默认会话信息
      if (isMobile) {
        session.mobileToken = token.mobileToken;
      }
      return session;
    },
  },
  secret: SECRET,
};

const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };

2. Web端认证实现

Web端直接使用NextAuth官方API,自动处理Cookie会话:

  • 登录:调用signIn("credentials", { email, password })
  • 获取会话:使用useSession()钩子
  • API路由验证:通过getServerSession(authOptions)判断用户权限
// app/api/protected/route.js
import { getServerSession } from "next-auth/next";
import { authOptions } from "../auth/[...nextauth]/route";

export async function GET() {
  const session = await getServerSession(authOptions);
  if (!session) return new Response("Unauthorized", { status: 401 });
  return new Response(JSON.stringify({ user: session.user }), { status: 200 });
}

3. 移动端JWT授权实现

React Native端登录时标记客户端类型,获取JWT后存入本地存储:

// 移动端登录请求
async function login(email, password) {
  const res = await fetch("http://your-nextjs-app/api/auth/signin/credentials", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-Client-Type": "mobile",
    },
    body: JSON.stringify({ email, password, callbackUrl: "http://localhost:3000" }),
  });
  const data = await res.json();
  if (data.mobileToken) {
    await AsyncStorage.setItem("authToken", data.mobileToken);
  }
}

// 移动端带JWT请求API
async function fetchProtectedData() {
  const token = await AsyncStorage.getItem("authToken");
  const res = await fetch("http://your-nextjs-app/api/protected", {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });
  return res.json();
}

移动端API验证逻辑

在Next.js API路由中同时兼容Web Session和移动端JWT验证:

// app/api/protected/route.js
import jwt from "jsonwebtoken";
import { getServerSession } from "next-auth/next";
import { authOptions } from "../auth/[...nextauth]/route";

const SECRET = process.env.NEXTAUTH_SECRET || "your-secret-key";

export async function GET(req) {
  // 优先校验Web端Session
  const session = await getServerSession(authOptions);
  if (session) {
    return new Response(JSON.stringify({ user: session.user }), { status: 200 });
  }

  // 校验移动端JWT
  const authHeader = req.headers.get("Authorization");
  if (!authHeader || !authHeader.startsWith("Bearer ")) {
    return new Response("Unauthorized", { status: 401 });
  }
  const token = authHeader.split(" ")[1];
  try {
    const decoded = jwt.verify(token, SECRET);
    const user = { id: decoded.userId, name: "Test User" };
    return new Response(JSON.stringify({ user }), { status: 200 });
  } catch (err) {
    return new Response("Invalid token", { status: 401 });
  }
}

更优方案:统一用JWT(Web+移动端)

如果想简化后端逻辑,推荐统一使用JWT策略:

  • Web端:NextAuth自动将JWT存储在HttpOnly Cookie中,和Session模式一样能防XSS攻击
  • 移动端:将JWT存入AsyncStorage,请求时携带Authorization头

配置NextAuth统一JWT策略

// app/api/auth/[...nextauth]/route.js
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";

export const authOptions = {
  providers: [
    CredentialsProvider({
      async authorize(credentials) {
        // 用户校验逻辑
        const user = { id: "1", name: "Test User", email: "test@example.com" };
        return user;
      },
    }),
  ],
  session: { strategy: "jwt" },
  callbacks: {
    async jwt({ token, user }) {
      if (user) token.userId = user.id;
      return token;
    },
    async session({ session, token }) {
      session.user.id = token.userId;
      // 可选:给移动端返回原始JWT
      if (req.headers.get("X-Client-Type") === "mobile") {
        session.token = token;
      }
      return session;
    },
  },
  secret: process.env.NEXTAUTH_SECRET,
};

const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };

这种方案下,Web端依然可以用useSession和getServerSession,移动端直接使用返回的JWT,后端无需区分客户端类型,维护成本更低。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 07:58:21