React登录认证控制器异常:无法从服务器获取数据求助
问题描述
我是React新手,在使用axios和jsonwebtoken实现服务器数据获取与路由功能时遇到登录认证控制器失效的问题。浏览器控制台未发现报错,但网站始终无响应,请求协助排查并修复。
相关代码
AuthController.js
import UserModel from "../Models/userModel.js"; import bcrypt from 'bcrypt' import jwt from "jsonwebtoken"; // Registering a new User export const registerUser = async (req, res) => { const { username, password, firstname, lastname } = req.body const salt = await bcrypt.genSalt(10) const hashedPass = await bcrypt.hash(password, salt) // req.body.passowrd = hashedPass const newUser = new UserModel({ username, password: hashedPass, firstname, lastname }) try { // check username const oldUser = await UserModel.findOne({ username }) if (oldUser) { return res.status(400).json({ message: "The username is already exist" }) } const user = await newUser.save() const token = jwt.sign({ username: user.username, id: user._id }, process.env.JWT_KEY, { expiresIn: '1h' }) res.status(200).json({ user, token }) } catch (error) { res.status(500).json({ message: error.message }) } }; // login user export const loginUser = async (req, res) => { const { username, password } = req.body; try { const user = await UserModel.findOne({ username: username }) if (user) { const validity = await bcrypt.compare(password, user.password); validity ? res.status(200).json(user) : res.status(400).json("Wrong Password") const token = jwt.sign( { username: user.username, id: user._id }, process.env.JWTKEY, { expiresIn: "1h" } ); res.status(200).json({ user, token }); } else { res.status(404).json("User not found"); } } catch (error) { res.status(500).json({ message: error.message }) } }
Auth Reducer
const authReducer = (state = { auhtData: null, loading: false, error: false }, action) => { switch (action.type) { case "AUTH_START": return { ...state, loading: true, error: false }; case "AUTH_SUCCES": localStorage.setItem("profile", JSON.stringify({ ...action?.data })) return { ...state, authData: action.data, loading: false, error: false }; case "AUTH_FAIL": return { ...state, loading: false, error: true } default: return state; } } export default authReducer
Auth Action
import * as AuthApi from '../api/AuthRequests.js'; export const logIn = (formData) => async (dispatch) => { dispatch({ type: "AUTH_START" }); try { const { data } = await AuthApi.logIn(formData); dispatch({ type: "AUTH_SUCCESS", data: data }); } catch (error) { console.log(error); dispatch({ type: "AUTH_FAIL" }); } }; export const signUp = (formData) => async (dispatch) => { dispatch({ type: "AUTH_START" }) try { const { data } = await AuthApi.signUp(formData) dispatch({ type: "AUTH_SUCCES", data: data }) } catch (error) { console.log(error) dispatch({ type: "AUTH_FAIL" }) } }
Auth Request for API
import axios from 'axios' const API = axios.create({ baseURL: "http://localhost:5000" }); export const logIn = (formData) => API.post('/auth/login', formData); export const signUp = (formData) => API.post('/auth/register', formData);
index.js
import express from "express"; import bodyParser from "body-parser"; import mongoose from "mongoose"; import dotenv from 'dotenv'; import cors from 'cors' import AuthRoute from './Routes/AuthRoute.js' import UserRoute from './Routes/UserRoute.js' import PostRoute from './Routes/PostRoute.js' //Routes const app = express(); // Middleware app.use(bodyParser.json({ limit: '30mb', extended: true, })) app.use(bodyParser.urlencoded({ limit: '30mb', extended: true, })) app.use(cors()) dotenv.config(); mongoose.connect(process.env.MONGO_DB, { useNewUrlParser: true, useUnifiedTopology: true }) .then(() => app.listen(process.env.PORT, () => console.log(`Listening to ${process.env.PORT}`))) .catch((error) => console.log(error)); // usage of routes app.use('/auth', AuthRoute) app.use('/user', UserRoute) app.use('/post', PostRoute)
问题排查与修复方案
1. 登录控制器重复响应(核心问题)
loginUser函数中,密码验证后已发送一次HTTP响应,但后续又再次发送响应。HTTP规范要求一个请求只能对应一个响应,重复响应会导致服务器内部报错,请求挂起无返回。
修复代码:
export const loginUser = async (req, res) => { const { username, password } = req.body; try { const user = await UserModel.findOne({ username: username }) if (!user) { return res.status(404).json("User not found"); } const validity = await bcrypt.compare(password, user.password); if (!validity) { return res.status(400).json("Wrong Password"); } // 统一环境变量名,与注册逻辑保持一致 const token = jwt.sign( { username: user.username, id: user._id }, process.env.JWT_KEY, { expiresIn: "1h" } ); res.status(200).json({ user, token }); } catch (error) { res.status(500).json({ message: error.message }) } }
2. 环境变量名不统一
注册逻辑使用process.env.JWT_KEY,但登录逻辑误写为process.env.JWTKEY,导致生成token失败,需统一环境变量名。
3. Reducer与Action的拼写错误
- Reducer初始状态中
auhtData拼写错误,应为authData - Action中注册成功的type为
AUTH_SUCCES(少写一个s),与登录逻辑的AUTH_SUCCESS不统一,需修正为一致的AUTH_SUCCESS
修复后的Reducer:
const authReducer = (state = { authData: null, loading: false, error: false }, action) => { switch (action.type) { case "AUTH_START": return { ...state, loading: true, error: false }; case "AUTH_SUCCESS": localStorage.setItem("profile", JSON.stringify({ ...action?.data })) return { ...state, authData: action.data, loading: false, error: false }; case "AUTH_FAIL": return { ...state, loading: false, error: true } default: return state; } }
修复后的Action注册逻辑:
export const signUp = (formData) => async (dispatch) => { dispatch({ type: "AUTH_START" }) try { const { data } = await AuthApi.signUp(formData) dispatch({ type: "AUTH_SUCCESS", data: data }) } catch (error) { console.log(error.response?.data || error.message); dispatch({ type: "AUTH_FAIL" }) } }
4. 错误日志优化
在Action的catch块中,打印error.response?.data可以获取服务器返回的具体错误信息,方便调试。
内容的提问来源于stack exchange,提问作者Dzy
相关产品推荐
相关产品推荐

