Axios withCredentials在NextJS中不起作用

pftdvrlh  于 2023-10-18  发布在  iOS
关注(0)|答案(2)|浏览(231)

即使正确设置了withCredentials,Axios也不会将Cookie发送到我的后端API。
前端(NextJS):

import axios from "axios"

const BASE_URL = "http://localhost:8000"

export default axios.create({
  baseURL: BASE_URL,
  headers: { "Content-Type": "application/json" },
  withCredentials: true,
})

前端登录(NextJS -下一次认证)

async authorize(credentials, req) {
        const res = await axios.post(
          "auth/signin",
          {
            email: credentials?.email,
            password: credentials?.password,
          }
        )
        console.log(res.headers)
        const user = await res.data
        if (user) {
          return user
        } else {
          return null
        }
      },

在上面的代码中,当我使用consloe.log读取头时,我可以清楚地看到我正确地从后端获取cookie:

AxiosHeaders {
  'x-powered-by': 'Express',
  'access-control-allow-origin': 'http://localhost:3000',
  vary: 'Origin',
  'access-control-allow-credentials': 'true',
  'set-cookie': [
    'site-auth.session-token=j%3A%7B%22accessToken%22%3A%22eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzaTNqc255cm50djdwMTRmenljY2UybWQiLCJlf_KU2ygyjCp096shZCXL_kQfR1U3LdYLSbPQ5VTSo%22%2C%22tokenId%22%3A%22clksubs1x00008z8nmospe1yk%22%7D; Domain=localhost; Path=/; Expires=Tue, 08 Aug 2023 21:58:03 GMT; HttpOnly; Secure; SameSite=None'
  ],
  'content-type': 'application/json; charset=utf-8',
  'content-length': '175',
  etag: 'W/"af-sE/2jElZ1eZqOhODKrhXa4Tz3xw"',
  date: 'Tue, 01 Aug 2023 21:58:03 GMT',
  connection: 'close'
}

但是当我尝试测试并获取用户配置文件时,我从Axios收到一个错误,指示API拒绝了请求。当我检查API日志时,我可以看到cookie没有被传递给它。
前端Axios调用配置文件端点:

const getProfile = async () => {
    const res = await axios.get("/user/profile")
    setProfile(res.data)
  }

”但是,我注意到一些重要的事情。我的API正在从Next-Auth获取其他cookie,这意味着Axios实际上正在发送cookie,但不是我创建的cookie。
另外,我可以在浏览器(Chrome)控制台中看到cookie列表,但看不到我创建的cookie

出于某种原因,我的cookie似乎没有被保存,或者Axios没有保存或发送它。
我已经使用Postman测试了我的API,一切都很好,我可以看到Postman正确地生成和使用cookie。
以下是关于后端API(NestJS)的更多信息
后端API(NestJS)

app.enableCors({
    origin: 'http://localhost:3000',
    methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
    preflightContinue: false,
    credentials: true,
    optionsSuccessStatus: 204,
  });

后端生成Cookie(NestJS)

res.cookie(
      'site-auth.session-token',
      {
        accessToken,
        refreshToken,
        tokenId,
      },
      {
        httpOnly: true,
        sameSite: 'none',
        domain: 'localhost',
        secure: true,
        expires: this.getRefreshExpiry(),
      },
    );
  • 请帮帮忙。我已经被卡住了几个小时,我无法继续我的应用程序。我在Google上搜索了很多,但没有希望。
deyfvvtc

deyfvvtc1#

对于Next.js,最好使用NextAuth.js处理身份验证。因为NextAuth.js和Axios解决了开发过程的不同部分。
Axios是浏览器和Node.js的基于Promise的HTTP客户端,使其成为发出HTTP请求的绝佳工具。但是处理auth有点棘手,特别是你刚刚开始使用Next.js。
另一方面,NextAuth.js是Next.js应用程序的完整开源身份验证解决方案。它旨在通过最小的API支持各种提供程序、JWT会话和数据库适配器。
所以我的建议是,为了更容易地解决这个问题,最好使用NextAuth.js来处理身份验证。在您的用例中,您使用Nest.js作为后端,使用NextAuth.js作为处理认证的Next.js库将是完全匹配的。

nukf8bse

nukf8bse2#

由于登录请求是在NextJS的服务器端发出的(NextAuth的 authorize 方法中的一个),因此从后端接收的cookie是在NextJS服务器上设置的,因此您必须将其转发到NextJS客户端会话。
现在要做到这一点,这取决于您使用的NextJS Router版本:

页面路由器Here is a good example on how to do it

简而言之:修改[...nextauth]路由处理程序,使其能够访问将发送给客户端的响应,并在其上设置cookie。

import { NextApiRequest, NextApiResponse } from 'next';
import NextAuth, { NextAuthOptions } from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';
import axios from 'axios'

type NextAuthOptionsCallback = (req: NextApiRequest, res: NextApiResponse) => NextAuthOptions

const nextAuthOptions: NextAuthOptionsCallback = (req, res) => {
     return {
        providers: [
           CredentialsProvider({
                credentials: {
                },
                async authorize(credentials) {
                   try {                      
                        const response = await axios.post('/api/login', {
                            username: credentials.username,
                            password: credentials.password
                        })

                        const cookies = response.headers['set-cookie']
                        // Send cookies to the browser
                        res.setHeader('Set-Cookie', cookies)

                        return response.data
                    } catch (error) {
                        console.log(error)
                        throw (Error(error.response))
                    } 
                }
           })
        ],
    }
}

export default (req: NextApiRequest, res: NextApiResponse) => {
    return NextAuth(req, res, nextAuthOptions(req, res))
}

应用路由器:我目前还不知道如何使用新的应用路由器访问客户端响应,但可以使用NextJS的中间件和NextAuth中间件来完成

// middleware.ts
import { NextResponse } from 'next/server';
import { getToken } from 'next-auth/jwt';
import { withAuth } from 'next-auth/middleware';

export default withAuth(
    // `withAuth` augments your `Request` with the user's token.
    async (req) => {
        const response = NextResponse.next();
        const cookies = req.cookies.getAll();

        if (cookies) {
            response.headers.set('Set-Cookie', cookies);
        }

        return response;
    },
);

export const config = {
    matcher: [
        /*
         * Match all request paths except for the ones starting with:
         * - api (API routes)
         * - _next/static (static files)
         * - _next/image (image optimization files)
         * - favicon.ico (favicon file)
         * - .*\\..* (public assets)
         */
        '/((?!api|_next/static|_next/image|.*\\..*|favicon.ico|robots.txt).*)',
    ],
};

相关问题