使用 NextJs 和 Next-Auth 时,getServerSession() 在 api 路由中返回 null

Mat*_*ell 6 next.js next-auth

我是 NextJS 和 Next-Auth 的新手。我正在尝试编写一个安全的 api 路由,该路由仅在用户登录时可用。我使用 useSession() 成功访问了客户端的会话,但是当我尝试在 api 路由中实现逻辑时,会话总是返回无效的。我尝试从文档中复制最简单的示例。我错过了什么吗?

这是我在 src/pages/api/users/getUser.ts 中的路线:

import { getServerSession } from 'next-auth/next'
import { authOptions } from '../auth/[...nextauth]'
import { NextApiRequest, NextApiResponse } from 'next'

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const session = await getServerSession(req, res, authOptions)
  console.log('session', session)

  if (session) {
    res.send({ content: 'SUCCESS' })
  } else {
    res.send({ error: 'ERROR' })
  }
}
Run Code Online (Sandbox Code Playgroud)

这是我在 src/pages/api/auth/[...nextauth].ts 中的 authOptions

import NextAuth from 'next-auth'
import GithubProvider from 'next-auth/providers/github'
import { PrismaAdapter } from '@next-auth/prisma-adapter'
import prisma from '../../../../prisma/db/prismadb'

export const authOptions = {
  adapter: PrismaAdapter(prisma),
  providers: [
    GithubProvider({
      clientId: process.env.GITHUB_ID || '',
      clientSecret: process.env.GITHUB_SECRET || '',
    }),
  ],
  pages: {
    signIn: '/',
    signOut: '/',
  },
}
Run Code Online (Sandbox Code Playgroud)

导出默认 NextAuth(authOptions)

这是我的依赖项:

 "dependencies": {
    "@next-auth/prisma-adapter": "^1.0.5",
    "@next/font": "13.1.6",
    "@prisma/client": "^4.10.1",
    "@types/node": "18.11.19",
    "@types/react": "18.0.27",
    "@types/react-dom": "18.0.10",
    "axios": "^1.3.2",
    "dotenv-cli": "^7.0.0",
    "eslint": "8.33.0",
    "eslint-config-next": "13.1.6",
    "next": "13.1.6",
    "next-auth": "^4.19.2",
    "prisma": "^4.9.0",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "styled-components": "^5.3.6",
    "typescript": "4.9.5"
  },
  "devDependencies": {
    "@types/styled-components": "^5.1.26"
  }
Run Code Online (Sandbox Code Playgroud)

小智 9

如果您从服务器组件调用 API 路由,则默认情况下不会通过 fetch 传递 cookie,因此您必须通过 API 调用发送标头。

所以你可以这样做:

import { headers } from "next/headers"

const response = await fetch("api/posts", {
  method: "GET",
  headers: headers()
})
Run Code Online (Sandbox Code Playgroud)

请注意,如果您在服务器组件中,则不必调用 API,您可以直接执行一些操作,例如从数据库获取数据或其他操作。

  • 这就是我的解决办法,谢谢 (2认同)

小智 1

就我而言,当 NEXTAUTH_URL 为 127.0.0.1 并且向 localhost 请求 API 时,会话为空。

因此,我通过将 NEXTAUTH_URL 与请求 URL 匹配来解决了该问题。