React项目Axios调用用户搜索接口返回401未授权问题求助
问题说明
开发React项目的用户搜索功能,通过Axios发起GET请求/api/user/allusers并携带search参数,空输入校验功能正常,但携带token请求时始终返回401 (Unauthorized)。前端已在请求头中添加Authorization: Bearer ${user.token},但后端认证中间件未识别到token。
代码片段
前端搜索请求代码
const handleSearch = async () => { if (!search) { toast({ title: "Please Enter something in search", status: "warning", duration: 5000, isClosable: true, position: "top-left", }); return; } try { setLoading(true); const config = { headers: { "Content-type": "application/json", Authorization: `Bearer ${user.token}`, }, withCredentials: true, }; const { data } = await axios.get(`http://localhost:5000/api/user/allusers?search=${search}`, config); setLoading(false); setSearchResult(data); } catch (error) { toast({ title: "Error Occured!", description: "Failed to Load the Search Results", status: "error", duration: 5000, isClosable: true, position: "bottom-left", }); console.log(error); } };
后端认证中间件代码
const isAuthenticatedUser = asyncHandler(async (req, res, next) => { const { token } = req.cookies; if (!token) { return next(new ErrorHandler("Please Login to access this resource", 401)); } const decodedData = jwt.verify(token, process.env.JWT_SECRET); req.user = await User.findById(decodedData.id); if (!req.user) { return next(new ErrorHandler("User does not exist", 401)); } next(); }); module.exports = isAuthenticatedUser;
问题根源
后端中间件仅从req.cookies中读取token,但前端是将token放在Authorization请求头里,两者获取token的方式不匹配,导致后端检测不到有效token,返回401。
解决方法
方法一:修改后端中间件,支持从Authorization头获取token
让中间件优先检查请求头的Authorization字段,若不存在再从cookie获取,兼容两种传参方式:
const isAuthenticatedUser = asyncHandler(async (req, res, next) => { let token; // 从Authorization Bearer头提取token if (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) { token = req.headers.authorization.split(' ')[1]; } // 头中无token则尝试从cookie获取 else if (req.cookies.token) { token = req.cookies.token; } if (!token) { return next(new ErrorHandler("Please Login to access this resource", 401)); } const decodedData = jwt.verify(token, process.env.JWT_SECRET); req.user = await User.findById(decodedData.id); if (!req.user) { return next(new ErrorHandler("User does not exist", 401)); } next(); });
方法二:修改前端,将token存入cookie
如果后端设计为依赖cookie传递token,前端登录成功后将token写入cookie,请求时通过withCredentials: true自动携带:
// 登录成功后设置cookie(示例使用js-cookie库,需先安装:npm install js-cookie) import Cookies from 'js-cookie'; // 假设登录接口返回user对象包含token Cookies.set('token', user.token, { expires: 7, // 有效期7天 secure: process.env.NODE_ENV === 'production', // 生产环境启用secure sameSite: 'strict' }); // 搜索请求中无需手动添加Authorization头,只需保留withCredentials const handleSearch = async () => { // ...空输入校验逻辑不变 try { setLoading(true); const config = { withCredentials: true, // 自动携带cookie }; const { data } = await axios.get(`http://localhost:5000/api/user/allusers?search=${search}`, config); setLoading(false); setSearchResult(data); } catch (error) { // ...错误处理逻辑不变 } };
额外注意事项
- 跨域配置:后端需开启CORS支持凭证,以Express为例:
const cors = require('cors'); app.use(cors({ origin: 'http://localhost:3000', // 前端域名 credentials: true })); - token有效性:确保前端传入的token未过期,且后端JWT签名密钥
process.env.JWT_SECRET与生成token时一致。
内容的提问来源于stack exchange,提问作者Deepshikha
相关产品推荐
相关产品推荐

