MERN博客应用动态个人主页创建失败,授权错误求助
问题分析与解决方案
你的核心问题是前端请求Profile数据时没有携带JWT授权令牌,导致后端的authorizations中间件验证失败,返回401授权错误。以下是具体修复步骤:
1. 前端请求添加Authorization头
在Profile页面的axios请求中,必须携带登录后存储的JWT令牌,格式为Bearer <token>。修改Profile.jsx的请求逻辑:
import { useParams } from "react-router-dom" import axios from "axios"; import { useEffect,useState } from "react"; const Profile = () => { const [data,setData] = useState(null); const params = useParams(); useEffect(()=>{ const fetchData = async()=>{ try { // 从本地存储获取登录时保存的token(根据你的登录逻辑调整存储位置) const authToken = localStorage.getItem('authToken'); if (!authToken) { console.error('No auth token found, please log in'); return; } const response = await axios.get(`http://localhost:4000/auth/user/${params.id}`, { headers: { Authorization: `Bearer ${authToken}` // 必须携带的授权头 } }); setData(response.data); } catch (error) { console.error('Error fetching data:', error.response?.data || error.message); } } fetchData(); },[params.id]) return ( <div> <h1>Profile page goes here</h1> <p>{JSON.stringify(data)}</p> </div> ) } export default Profile
2. 确认登录逻辑正确存储Token
确保登录成功后,将后端返回的JWT令牌保存到本地存储(或状态管理工具)。示例登录页面的处理逻辑:
// LogIn.jsx 示例代码 const handleLogin = async (e) => { e.preventDefault(); try { const res = await axios.post('http://localhost:4000/auth/login', { email: yourEmailState, password: yourPasswordState }); // 保存token到localStorage localStorage.setItem('authToken', res.data.token); // 登录成功后跳转 navigate('/'); } catch (err) { console.error('Login failed:', err.response?.data); } }
3. 修复后端授权中间件的模型名称错误
你的后端授权代码中使用了users.findOne,但API端点里用的是user.findById,推测模型导入名称应为user而非users,否则会导致模型未定义错误,间接触发授权失败:
// 后端授权验证代码修改 const jwt = require('jsonwebtoken') const user = require('../models/user'); // 确保正确导入用户模型 require('dotenv').config(); exports.authorizations = async (req, res, next) => { const { authorization } = req.headers; if (!authorization) { return res.status(401).json({ error: 'Authorization token required' }); } const token = authorization.split(' ')[1]; req.token = token; if (token) { try { const { _id } = jwt.verify(token, process.env.SECRET); // 把users改为user,匹配你的模型导入 req.user = await user.findOne({ _id }).select('_id'); next(); } catch (error) { if (error.name === 'TokenExpiredError') { res.status(401).send('Token has expired, please login again'); } else { res.status(401).send('Invalid token'); } } } else { res.status(401).send('Not authenticated, invalid token'); } };
4. 优化前端路由顺序(可选但推荐)
将动态路由/:id放在子路由的最后,避免它错误匹配其他固定路由(如/signup、/LogIn):
<Route element={<Layout/>} > <Route path='/' element={<Home/>} /> <Route path='newstory' element={<Write/>} /> <Route path='signup' element={<SignUp/>} /> <Route path='LogIn' element={<LogIn/>} /> <Route path='/:id' element={<Profile/>} /> {/* 移到最后 */} </Route>
内容的提问来源于stack exchange,提问作者Mazhar Ansari
相关产品推荐
相关产品推荐

