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
相关产品推荐
相关产品推荐

