注册后获取用户时提示"未提供Token"问题求助
问题排查:注册后调用getUser接口提示"Access denied. No token provided"
注册用户后调用getUser接口时,抛出"Access denied. No token provided"错误,无法正常传递Token获取用户信息。以下是相关代码及排查修复方案:
相关代码
jwtToken.js
export const sendToken = (user, statusCode, res, message) => { const token = user.getJWTToken(); const options = { expires: new Date( Date.now() + process.env.COOKIE_EXPIRE * 24 * 60 * 60 * 1000 ), httpOnly: true, // Set httpOnly to true }; res.status(statusCode).cookie("token", token, options).json({ success: true, user, message, token, }); };
auth.js
import { User } from "../models/userSchema.js"; import { catchAsyncError } from "./catchAsyncError.js"; import ErrorHandler from "./error.js"; import jwt from "jsonwebtoken"; export const isAuthorized = catchAsyncError(async (req, res, next) => { // get token from cookies const { token } = req.cookies; // Checking if there is No token or user doesn't registerd yet if (!token) { return next(new ErrorHandler("Access denied. No token provided", 401)); } // if token exists then verify the secret key is same as we declayerd const decoded = jwt.verify(token, process.env.JWT_SECRET_KEY); req.user = await User.findById(decoded.id); next(); });
getUser接口
export const getUser = catchAsyncError((req, res, next) => { const user = req.user; res.status(200).json({ success: true, user, }); });
前端注册函数handleRegister
const handleRegister = async (e) => { e.preventDefault(); try { const { data } = await axios.post( "http://127.0.0.1:8000/api/v1/user/register", { name, email, role, password }, { headers: { "Content-Type": "application/json" }, withCredentials: true, } ); toast.success("Successfully Registerd!"); setName(""); setEmail(""); setPassword(""); setRole(""); setIsAuthorized(true); } catch (error) { toast.error(error.response.data.message); } };
前端获取用户函数fetchuser
// works whenever isAuthorized is changed useEffect(() => { const fetchuser = async () => { try { // get and set user using axios const res = await axios.get("http://127.0.0.1:8000/api/v1/user/getuser", { withCredentials: true }); setUser(res.data.user); setIsAuthorized(true); } catch(error) { setIsAuthorized(false); } }; fetchuser(); }, [isAuthorized] ); // changing value of isAuthorized
排查与修复方案
1. 后端未配置跨域凭证允许
如果前端和后端处于跨域环境(比如前端跑在3000端口,后端8000端口),后端必须配置CORS允许携带凭证。以Express为例:
const cors = require('cors'); app.use(cors({ origin: 'http://localhost:3000', // 替换为你的前端实际地址 credentials: true // 关键:允许携带Cookie等凭证 }));
2. 缺少cookie-parser中间件
后端需要cookie-parser解析请求中的Cookie,否则req.cookies会是空对象。执行以下步骤:
- 安装依赖:
npm install cookie-parser
- 在Express入口文件中配置:
const cookieParser = require('cookie-parser'); app.use(cookieParser());
3. Cookie的SameSite属性缺失
跨域场景下,默认的Cookie SameSite策略会阻止浏览器携带Cookie。修改sendToken中的Cookie配置:
const options = { expires: new Date( Date.now() + process.env.COOKIE_EXPIRE * 24 * 60 * 60 * 1000 ), httpOnly: true, sameSite: process.env.NODE_ENV === 'production' ? 'None' : 'Lax', secure: process.env.NODE_ENV === 'production' // 生产环境必须开启HTTPS才能生效 };
4. useEffect依赖逻辑问题
注册后设置isAuthorized = true会触发useEffect,但此时浏览器可能还未完成Cookie存储。调整逻辑:
- 注册成功后直接调用
fetchuser,而非依赖状态变化 - 简化useEffect的依赖,仅在组件挂载时调用一次
修改后的handleRegister:
const handleRegister = async (e) => { e.preventDefault(); try { const { data } = await axios.post( "http://127.0.0.1:8000/api/v1/user/register", { name, email, role, password }, { headers: { "Content-Type": "application/json" }, withCredentials: true, } ); toast.success("Successfully Registerd!"); // 重置表单 setName(""); setEmail(""); setPassword(""); setRole(""); // 注册成功后直接获取用户信息 await fetchuser(); } catch (error) { toast.error(error.response.data.message); setIsAuthorized(false); } };
修改后的useEffect:
useEffect(() => { fetchuser(); }, []); // 仅在组件挂载时调用一次
内容的提问来源于stack exchange,提问作者AYUSH SINGH BHATI
相关产品推荐
相关产品推荐

