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

React应用Logout功能失效,但Postman请求正常的问题

React登出接口401未授权问题排查与解决

问题背景

React应用中点击登出按钮调用后端logout接口时返回401未授权,但Postman请求该接口能正常得到成功响应。相关代码如下:

React前端登出逻辑

async function logOutHandle(e){
    e.preventDefault();

    try {
      
      const response = await axios.post("http://localhost:3000/api/v1/users/logout",{withCredentials: true});
      console.log(response)
      if(response.status===200)
      {
        history('/')
      }
      
    } catch (error) {
      console.log(error);
    }

  } 

后端登录控制器(生成JWT到HttpOnly Cookie)

const login= async (req,res)=>{
    try {
        const {email,password}=req.body;
        const user= await User.findOne({email});
        if(!user){
            return res.status(404).json({error: "Account not found"});
        }
        if(user.email == email && user.password==password)
        {
            const payload = {
                user: user.id // 假设user.id是MongoDB的ObjectId
              };
            const token = jwt.sign(payload, process.env.SECRATE_KEY, {
                expiresIn: '1h', // Token过期时间
            });
            res.cookie('token', token, {
                httpOnly: true,
                maxAge: 1000 *60*60, // 1小时
              });
              
              
            res.status(201).json({ token, msg: 'Log in Successful' });
        }else{
        res.status(401).json({error:"Check your password or email"});
        }
    } catch (error) {
        res.status(500).json({msg:error});
    }
} 

后端登出控制器(清除Cookie)

const logout= (req,res)=>{
    try {
        // 通过设置空值并立即过期清除token cookie
        res.cookie('token', 'none', { expiresIn:5000, httpOnly: true });
        res.status(200).json({ msg: 'Logged out successfully' });
      } catch (error) {
        // 处理登出过程中可能出现的错误
        console.error(error);
        res.status(500).json({ error: 'An error occurred during logout' });
      }
} 

核心问题与解决办法

1. Axios的withCredentials配置位置错误

你把withCredentials: true放在了请求体参数里,这是错误的。该配置属于Axios的请求配置项,需要作为第三个参数传入:

修改前端登出函数:

async function logOutHandle(e){
    e.preventDefault();

    try {
      // withCredentials放在请求配置项中,而非请求体
      const response = await axios.post(
        "http://localhost:3000/api/v1/users/logout",
        {}, // 登出无需请求体,传空对象占位
        { withCredentials: true }
      );
      console.log(response);
      if(response.status===200) {
        history('/');
      }
      
    } catch (error) {
      console.log(error);
    }
} 

2. 后端CORS必须明确允许携带凭证

即使排查过CORS,也要确认后端配置是否满足两个关键条件:

  • 不能用*作为允许的源,必须指定前端具体域名(比如http://localhost:3001)
  • 开启credentials: true允许携带Cookie

以Express为例,正确的CORS配置:

const cors = require('cors');
app.use(cors({
  origin: 'http://localhost:你的React端口号',
  credentials: true
}));

3. 后端清除Cookie的参数错误

res.cookie方法没有expiresIn参数,需要用expires或maxAge来设置过期时间,同时建议补充sameSite和secure参数增强安全性:

修改后端logout控制器:

const logout= (req,res)=>{
    try {
        res.cookie('token', 'none', { 
            expires: new Date(Date.now() + 5000), // 5秒后过期
            httpOnly: true,
            secure: process.env.NODE_ENV === 'production', // 生产环境开启HTTPS时启用
            sameSite: 'strict' // 防止CSRF攻击,可根据场景调整为'lax'
        });
        res.status(200).json({ msg: 'Logged out successfully' });
      } catch (error) {
        console.error(error);
        res.status(500).json({ error: 'An error occurred during logout' });
      }
} 

4. 确认后端登出接口的验证逻辑

如果后端对logout接口做了JWT验证,要确保验证中间件是从Cookie中提取token,而非请求头:

示例JWT验证中间件:

const authMiddleware = (req, res, next) => {
  const token = req.cookies.token; // 从Cookie获取token
  if (!token) {
    return res.status(401).json({ error: '未授权' });
  }
  try {
    const decoded = jwt.verify(token, process.env.SECRATE_KEY);
    req.user = decoded.user;
    next();
  } catch (err) {
    res.status(401).json({ error: 'Token无效' });
  }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 01:40:14