1

我有一个用 Laravel 和 Sanctum 构建的 API。

前端是用 NextJS 构建的。CORS 和通信运行良好 - 显然,即使使用 POST 请求,我也看不到错误。

登录很顺利,Laravel 为.mydomain.com路径“/”设置了一个 cookie,并且它只是 HTTP。好的。控制台中没有错误。我可以使用 Laravel Sanctum 的 JWT 在 chrome 开发工具中看到 cookie。

好的,所以在提交登录表单并收到带有jwtcookie/token的成功响应后,用户将被重定向到主页。在 NextJS 主页中,我有一个功能可以检查会话在 Laravel API 中是否仍然有效。这个函数在getServerSideProps钩子中运行,也就是 NodeJS。为此,从 NextJS 服务器(NodeJS)向 Laravel API 发出 POST 请求,试图获取有关用户的信息。在这个请求中,cookie 被“转发”到 Laravel。但奇怪的是:请求永远不会到达 Laravel。它正在“命中” NextJS API 路由。而且,当然,该路线在 Next 中不存在。它应该请求 Laravel API。

所以,一步一步:

  1. 用户mydomain.com/login从 NextJS 键入并获取登录页面。
  2. 用户填写并提交表单。React(客户端)使用 Axios 在api.mydomain.com/api/login.
  3. Laravel API 验证表单并jwt在响应中设置一个 cookie:
 3.1) HTTP Only
 3.2) Path: `/`
 3.3) Domain: `.mydomain.com` (accordingly to `RFC 6265`
 3.4) Value: the JWT token from Laravel Sanctum
  1. 在 React 使用 cookie 获得登录响应后jwt,React 代码将用户重定向到mydomain.com/(根 URL)。这是问题的开始。

  2. NextJS 将在服务器端运行/构建主页。在 NextJS 的 SSR 期间,Homepage 使用getServerSidePropsNextJS 中的 hook,并尝试调用api.mydomain.com/api/me以验证 session/cookie/jwt。但是,由于未知原因,它实际上调用了mydomain.com/api/me. 请注意,我的 API 在子域中运行api.mydomain.com,NextJS 在mydomain.com.

看起来 Axios 正在“忽略”baseURL配置。但我什至用绝对路径、硬编码的子域替换了相对 URL。仍然看到同样的错误。首先,它导致了 404 页面——因为 NextJS 没有/pages/api/me.ts文件。我花了很长时间才想到:“嘿,也许这个请求会发送给 NextJS 本身,而不是 Laravel API”。因此,我在 NextJS 中放入了一个输出以下句子的文件:

EERRRROOORRRRRR!!!!永远不应该调用这个,因为 LARAVEL 应该响应这个调用,而不是 NEXTJS API !!!!!!

我可以在日志中看到这个响应。这是我的 HTTP 方法:


export async function me(headers: Headers = {}): Promise<User> {
  try {
    const config = {
      baseURL: 'api.mydomain.com/api',
      withCredentials: true,
      headers: {
        ...headers,
      },
    };
    console.log('config', config);

    // I was using a global configured instance, but now I'm creating a new one here:
    const tempAxios = axios.create(config);

    console.log('call HTTP me(). Config:', config);
    // the "space" between // and api is only because Stackoverflow blocks URL in the post
    const { data } = await tempAxios.get('https:// api.mydomain.com/api/user');
    return Promise.resolve(data);
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
  } catch (error: any) {
    console.error('call HTTP me() ERROR', error.config);
    return Promise.reject(error);
  }
}

然后,我可以在 NextJS / Node 日志中看到:

[app-frontend] [2022-03-03 23:39:12] call HTTP me(). Config: {
[app-frontend] [2022-03-03 23:39:12]   baseURL: 'api.mydomain.com/api',
[app-frontend] [2022-03-03 23:39:12]   withCredentials: true,
[app-frontend] [2022-03-03 23:39:12]   headers: {
[app-frontend] [2022-03-03 23:39:12]     host: 'mydomain.com',
[app-frontend] [2022-03-03 23:39:12]     'accept-encoding': 'gzip',
[app-frontend] [2022-03-03 23:39:12]     'x-forwarded-for': '2001:818:e889:6600:f4f5:79c0:beb7:etc etc etc',
[app-frontend] [2022-03-03 23:39:12]     'x-forwarded-proto': 'https',
[app-frontend] [2022-03-03 23:39:12]     'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"',
[app-frontend] [2022-03-03 23:39:12]     'sec-ch-ua-mobile': '?0',
[app-frontend] [2022-03-03 23:39:12]     'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36',
[app-frontend] [2022-03-03 23:39:12]     'sec-ch-ua-platform': '"macOS"',
[app-frontend] [2022-03-03 23:39:12]     accept: '*/*',
[app-frontend] [2022-03-03 23:39:12]     'sec-fetch-site': 'same-origin',
[app-frontend] [2022-03-03 23:39:12]     'sec-fetch-mode': 'cors',
[app-frontend] [2022-03-03 23:39:12]     'sec-fetch-dest': 'empty',
[app-frontend] [2022-03-03 23:39:12]     referer: 'mydomain.com/login',
[app-frontend] [2022-03-03 23:39:12]     'accept-language': 'pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7',
[app-frontend] [2022-03-03 23:39:12]     cookie: 'jwt=75%7C4VyknPf8Jb2papbla-bla-bla',
[app-frontend] [2022-03-03 23:39:12]     'cdn-loop': 'cloudflare',
[app-frontend] [2022-03-03 23:39:12]     'do-connecting-ip': '2001:818:etc',
[app-frontend] [2022-03-03 23:39:12]     'Content-Type': 'application/json',
[app-frontend] [2022-03-03 23:39:12]     Accept: 'application/json'
[app-frontend] [2022-03-03 23:39:12]   }
[app-frontend] [2022-03-03 23:39:12] }
[app-frontend] [2022-03-03 23:39:12] EERRRROOORRRRRR!!!! THIS SHOULD NEVER BE CALLED, SINCE LARAVEL SHOULD ANSWER THIS CALL, NOT NEXTJS API!!!!!

上面日志的最后一行只存在,因为 Axios 在 NextJS SSR 期间调用了错误的域。所以,无论我做什么,请求总是命中mydomain.com/api/me,而不是api.mydomain.com. 我在 DigitalOcean Apps 平台上完成所有这些工作。使用控制台,我可以手动运行debug.js类似的文件node debug.js,它可以正确获取 URL/有效负载。但是,在 NextJS 中,baseURL被忽略了,请求总是转到 NextJS。

我不知道我还应该在这里做什么。因为login路线很好。我不确定是否是因为config.headers.host这阻止了请求转到子域。

非常感谢任何帮助。

4

0 回答 0