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

Next.js 14客户端获取用户Profile数据失败,请求协助排查

问题排查与解决方案

可能原因分析

  1. 跨域资源共享(CORS)配置缺失
    浏览器的同源策略会限制前端跨域请求,Postman和直接访问API不受此限制,但Axios请求会被拦截。若后端未配置允许前端域名的跨域规则,请求会被浏览器阻断,导致Axios无法获取正常响应。

  2. 令牌格式或有效性问题

    • Authorization头格式错误:必须严格遵循Bearer <token>格式,注意Bearer与令牌之间的空格不能省略
    • localStorage中的jwt值异常:可能存在多余引号、转义字符或内容截断
  3. 错误日志不完整
    当前catch块仅打印error,但Axios错误对象包含response(后端返回的错误详情)、message等字段,仅打印error无法定位具体问题。

  4. 状态更新的异步特性
    setCount是异步操作,依赖count的useEffect触发时,可能count还未更新为有效token值,导致请求携带无效令牌。


分步解决方案

1. 修复后端CORS配置

后端需允许前端所在域名(如http://localhost:3000)的跨域请求,同时放行Authorization请求头。

以Express后端为例,添加cors中间件:

const cors = require('cors');
app.use(cors({
  origin: 'http://localhost:3000', // 前端Next.js应用地址
  allowedHeaders: ['Authorization', 'Content-Type'],
  methods: ['GET', 'POST', 'PUT', 'DELETE']
}));

以Spring Boot后端为例,添加CORS配置类:

@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(Collections.singletonList("http://localhost:3000"));
        config.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"));
        config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

2. 验证令牌与请求头

在getUserProfile函数中添加日志,确认令牌格式与内容:

const getUserProfile = async () => {
  try {
    const token = count;
    console.log("Token from localStorage:", token); // 检查令牌完整性
    if (!token) {
      console.error("No token found in local storage");
      return;
    }

    console.log("Authorization header:", `Bearer ${token}`); // 检查头格式
    const response = await axios.get("http://localhost:8080/api/v1/profile", {
      headers: { Authorization: `Bearer ${token}` },
    });

    console.log("Full API response:", response); // 打印完整响应
    setUserProfile(response.data);
  } catch (error) {
    // 打印完整错误信息
    console.error("Error details:", {
      message: error.message,
      response: error?.response?.data,
      status: error?.response?.status
    });
  }
};

3. 优化状态逻辑

重命名状态变量提升可读性,同时避免状态更新的异步延迟:

"use client";
import React, { useState, useEffect } from "react";
import axios from "axios";

const Page = () => {
  const [authToken, setAuthToken] = useState(null);
  const [userProfile, setUserProfile] = useState(null);

  useEffect(() => {
    const savedToken = localStorage.getItem("jwt");
    setAuthToken(savedToken);
    // 直接调用,无需等待state更新
    if (savedToken) {
      getUserProfile(savedToken);
    }
  }, []);

  const getUserProfile = async (token) => {
    try {
      if (!token) {
        console.error("No token provided");
        return;
      }

      const response = await axios.get("http://localhost:8080/api/v1/profile", {
        headers: { Authorization: `Bearer ${token}` },
      });

      setUserProfile(response.data);
    } catch (error) {
      console.error("Error fetching user profile:", {
        message: error.message,
        responseData: error?.response?.data,
        statusCode: error?.response?.status
      });
    }
  };

  // 处理token后续变化的情况
  useEffect(() => {
    if (authToken) {
      getUserProfile(authToken);
    }
  }, [authToken]);

  return (
    <div>
      user dashboard: {userProfile?.name || "Loading..."}
    </div>
  );
};

export default Page;

4. 检查Axios全局拦截器

若项目配置了Axios全局拦截器,确保未修改或丢弃响应数据:

// 确认响应拦截器返回完整response
axios.interceptors.response.use(
  (response) => response, // 必须返回response,否则后续会拿到undefined
  (error) => Promise.reject(error)
);

内容的提问来源于stack exchange,提问作者Shahin Azizi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 18:53:20