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

React/Express应用登录遇Axios 404错误,求排查方案

问题排查与修复方案

核心问题1:Axios请求地址缺失后端端口(直接导致404)

你的API.js里axios.post(login, ...)只写了路径,前端会默认把请求发到当前前端域名(localhost:3000),但后端跑在3001端口,自然找不到对应路由,触发404错误。

两种修复方式:

  • 方案一:直接写完整后端地址
    const res = await axios.post(`http://localhost:3001/login`, { username, password });
    
  • 方案二:React项目配置代理(推荐,同时解决跨域)
    在项目根目录的package.json里添加一行:
    "proxy": "http://localhost:3001"
    
    配置后请求可以保持/login,React会自动把请求转发到后端端口。

核心问题2:前端错误生成JWT(逻辑完全倒置)

API.js里你在前端生成了JWT,但正确流程是后端验证用户合法性后生成token返回给前端,前端只需要存储后端返回的token即可。你现在的逻辑会导致前端生成的token和后端完全无关,没有任何验证作用。

修复API.js的login方法:

static async login(data) {
    const { username, password } = data;
    // 用上面配置好的路径
    const res = await axios.post(`/login`, { username, password });
    
    if (res.status === 200) {
        this.token = res.data.token; // 直接使用后端返回的token
        return res.data.token;
    } else {
        throw new Error(res.data.error?.message || '登录失败');
    }
};

核心问题3:LoginForm错误处理API返回值

API.login方法返回的是token字符串,不是axios响应对象,所以你在handleSubmit里判断res.status === 200会直接报错——字符串根本没有status属性。

修复LoginForm的handleSubmit:

const handleSubmit = async (e) => {
    e.preventDefault();
    const data = { username, password };
    try {
        const token = await LearnGuruApi.login(data);
        setToken(token); // 直接存储返回的token
        // 这里可以添加登录成功后的逻辑,比如跳转到首页
    } catch (err) {
        console.error('登录失败:', err.message);
    }
};

额外问题:后端未验证种子用户合法性

当前后端路由只检查了用户名和密码是否为空,没有验证是否是数据库中存在的种子用户,这会导致任何非空的用户名密码都能拿到token,完全不符合登录认证的逻辑。

修复后端login路由(假设你有User模型):

app.post("/login", async (req, res) => {
    const { username, password } = req.body;

    if (!username || !password) {
        return res.status(401).json({ error: { message: '用户名或密码不能为空' } });
    }

    // 查询数据库中的种子用户
    const user = await User.findOne({ username });
    if (!user) {
        return res.status(401).json({ error: { message: '用户不存在' } });
    }

    // 验证密码(假设密码是哈希存储,用bcrypt举例)
    const isPasswordValid = await bcrypt.compare(password, user.password);
    if (!isPasswordValid) {
        return res.status(401).json({ error: { message: '密码错误' } });
    }

    const token = jwt.sign({ username: user.username }, secret, { expiresIn: '1h' });
    res.status(200).json({ token });
});

补充:跨域问题兜底处理

如果没配置代理,后端需要添加CORS中间件:

  1. 安装依赖:npm install cors
  2. 在server.js里添加:
const cors = require('cors');
app.use(cors()); // 生产环境建议配置指定域名白名单,不要直接允许所有跨域

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 08:43:19