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

React中Axios注册请求JWT认证400错误排查与修复

问题:React JWT注册请求返回400 Bad Request但MongoDB用户已创建

在React应用中实现JWT Token认证,发送Axios POST请求完成新用户注册时,收到400 Bad Request错误,但MongoDB用户集合确实正常更新了,请求URL和端点配置正确,求解决方法。


前端代码

App.js

function App() {
const [token, setToken] = useState(false);
const [userId, setUserId] = useState(false);

const login = useCallback((uid, token)=> {
setToken(true);
setUserId(uid)
},[]);

const logout = useCallback(()=> {
setToken(null);
setUserId(null);
},[]);

let routes;

if(token) {
routes = (
        <Routes>
        <Route path="/" element={<HomePage >} />
        <Route path="/product-detail" element={<ProductDetailPage />} />
        <Route path="/sub-category" element={<SubCategory />} />
        <Route path="/saved" element={<SavedPage />} />
        <Route path="/inbox" element={<InboxPage />} />
        <Route path="/deals" element={<DealsPage />} />
      </Routes>
    )
} else {
routes = (
      <Routes>
        <Route path="/" element={<HomePage />} />
        <Route path="/product-detail" element={<ProductDetailPage />} />
        <Route path="/sub-category" element={<SubCategory />} />
      </Routes>
    )
}

return (
<AuthContext.Provider value={{
isLoggedIn: !!token,
token: token,
userId : userId,
login : login,
logout: logout } }}>
    <BrowserRouter>
    <ChakraProvider theme={theme}>
      {routes}
    </ChakraProvider>
    </BrowserRouter>
    </AuthContext.Provider>
);
}

export default App;

注册Formik表单

const auth = useContext(AuthContext);

const signUpFormik = useFormik({
initialValues : {
firstName : "",
lastName : "",
location : "",
email : "",
password : "",
},
onSubmit : async (values) => {
try {
const res = await axios.post("http://localhost:3005/user/signup", values, {
headers: {
"Authorization" : "Bearer " + auth.token,
},
});
auth.login(res.data.userId, res.data.token)
console.log(res.data);
} catch (error) {
console.error(error);
console.log(error.response);
}
}});

AuthContext状态管理

import { createContext } from "react";

export const AuthContext = createContext({
isLoggedIn: false,
userId: null,
token : null,
login : () => {},
logout : () => {}
});

后端代码

check-auth.js 中间件

import HttpError from "../models/http-error.js";
import jwt from "jsonwebtoken";

export const checkAuth = (req,res,next) => {
    try {
        const token = req.headers.authorization.split(' ')[1];
        if (!token) {
            throw new Error('Authentication failed!');
        }
        const decodedToken = jwt.verify(token, 'supersecretkey');
        req.userData = { userId : decodedToken.userId }
        next();
    } catch (err) {
        const error = new HttpError('Authentication failed', 401);
        return (error); 
    }
}

注册控制器 userSignUp

export const userSignUp = async (req, res) => {
    const {
      firstName,
      lastName,
      email,
      password,
      location,
    } = req.body;
    
    const passwordHash = await bcrypt.hash(password, 12);
    
    const user = new User({
      _id: new mongoose.Types.ObjectId(),
      firstName,
      lastName,
      email,
      password : passwordHash,
      location,
    });
    
    try {
      let token;
      token = jwt.sign({userId : user.id, email : user.email }, 
      'supersecretkey', 
      { expiresIn : '1h', }
      );
    } catch (err) {
      console.log(err);
      console.log(err.response)
    }
    
    try {
      const savedUser = await user.save();
      res.status(200).json(savedUser, token);
    } catch (error) {
      res.status(400).json({
        message: "Error creating user",
        error,
      });
    }
};

问题根源与修复方案

1. 注册请求错误携带Authorization头

注册是开放接口,无需已登录用户的Token,但你在请求中添加了Authorization: Bearer + auth.token,此时用户未登录,auth.token初始值为false,会导致请求头格式错误。如果后端给注册接口配置了checkAuth中间件,会直接抛出认证失败错误。

修复:移除注册请求的Authorization头:

const res = await axios.post("http://localhost:3005/user/signup", values);

同时检查后端路由,确保注册接口未使用checkAuth中间件。

2. 后端响应格式错误

res.status(200).json(savedUser, token)是错误用法,res.json()仅接受一个参数。需要将用户信息和Token封装到同一对象中返回。

修复:

// 把token提升到外层作用域,避免块级作用域无法访问
let token;
try {
  token = jwt.sign({userId : user.id, email : user.email }, 
  'supersecretkey', 
  { expiresIn : '1h', }
  );
} catch (err) {
  console.log(err);
  // 这里要返回错误响应,而非仅打印
  return res.status(500).json({message: "Failed to generate token", error: err});
}

try {
  const savedUser = await user.save();
  res.status(201).json({
    userId: savedUser._id,
    token: token,
    user: savedUser
  });
} catch (error) {
  res.status(400).json({
    message: "Error creating user",
    error,
  });
}

3. App.js中Token初始值错误

你用useState(false)作为token初始值,但AuthContext默认token为null,会导致登录状态判断逻辑混乱。未登录时token应设为null。

修复:

const [token, setToken] = useState(null);
const [userId, setUserId] = useState(null);

4. checkAuth中间件错误处理问题

中间件中return (error)无法正确传递错误,应使用next(error)或直接发送响应。另外要先判断是否存在Authorization头,避免split方法报错。

修复:

export const checkAuth = (req,res,next) => {
    try {
        if (!req.headers.authorization) {
            throw new Error('Authentication failed!');
        }
        const token = req.headers.authorization.split(' ')[1];
        if (!token) {
            throw new Error('Authentication failed!');
        }
        const decodedToken = jwt.verify(token, 'supersecretkey');
        req.userData = { userId : decodedToken.userId }
        next();
    } catch (err) {
        const error = new HttpError('Authentication failed', 401);
        return next(error);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 00:04:03