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

跨域资源共享(CORS)阻止同WiFi设备连接项目的问题排查

问题描述

本地通过localhost:3000访问项目完全正常,但同一WiFi下的iPhone、iPad通过http://192.168.50.6:3000访问时,能加载登录页面,但登录请求被CORS拦截。已将iOS设备的本地IP添加到allowedOrigins列表中,但问题依旧。


现有CORS配置代码

const allowedOrigins = ['http://localhost:3000', 'http://192.168.50.52', 'http://192.168.50.121'];
const corsOptions = {
  origin: function (origin, callback) {
    // Allow requests with no origin (like mobile apps or curl requests)
    if (!origin) return callback(null, true);
    if (allowedOrigins.indexOf(origin) !== -1) {
      callback(null, true); // Origin is allowed
    } else {
      callback(new Error('CORS not allowed for this origin')); // Origin is not allowed
    }
  },
  credentials: true,
  optionsSuccessStatus: 200
};

app.use(cors(corsOptions));
app.options('*', cors(corsOptions)); // Enable pre-flight across-the-board

服务器路由代码

// MARK: Routes server
app.get('/', (req, res) => {
    console.log("SERVER response to get /");
    if (req.session.isAuthenticated) {
        res.status(200).json({
          message: "Welcome to the homepage!",
          userInfo: req.session.userInfo  // Ensure userInfo is passed correctly
        });
      } else {
        console.log('Unauthorized reuqest to /');
        res.status(401).json({ error: "Unauthorized" });
      }
  });


//MARK: Login
app.post('/login', (req, res) => {
    console.log("SERVER response to post Login");
    const { staffNumber, password } = req.body;
    console.log('staffnumber:', staffNumber, 'password:', password);
    // query to the database to check if the user exist field staff_number and password
    db.query('SELECT * FROM amu_users WHERE staff_number = $1 AND password = $2', [staffNumber, password], (err, result) => {
        if (err) {
            console.error('Error executing query', err);
            res.status(500).send('Internal server error');
            
        } else {
            
            if (result.rows.length === 1) {
                // the user is authenticated
                req.session.userInfo = result.rows[0];
                req.session.isAuthenticated = true;
                res.status(200)
                res.json({result:'success', userInfo: req.session.userInfo});

                
            } else {
                res.status(401).send('Unauthorized');
                
            }
        }
    });
});

问题排查与修复方案

1. Origin匹配不完整

iOS设备浏览器发送的请求Origin可能包含端口号(比如http://192.168.50.52:3000),但你配置的allowedOrigins中只添加了不带端口的IP。登录页面能加载是因为静态资源请求未触发严格CORS校验,但POST登录请求的预检请求会严格验证Origin。

  • 修复:在allowedOrigins中补充带端口的完整Origin:
    const allowedOrigins = [
      'http://localhost:3000',
      'http://192.168.50.52:3000',
      'http://192.168.50.121:3000'
    ];
    

2. CORS错误处理逻辑错误

当前代码中,若Origin不在允许列表,直接抛出错误会导致服务器返回500状态码,而非标准的CORS拒绝响应。正确做法是返回false给callback,让CORS中间件自动处理响应头。

  • 修复:修改CORS配置的错误分支:
    const corsOptions = {
      origin: function (origin, callback) {
        if (!origin) return callback(null, true);
        if (allowedOrigins.indexOf(origin) !== -1) {
          callback(null, true);
        } else {
          // 不抛出错误,返回false让中间件处理拒绝逻辑
          callback(null, false);
        }
      },
      credentials: true,
      optionsSuccessStatus: 200
    };
    

3. 登录路由响应写法不规范

登录路由中res.status(200)和res.json(...)分开调用,虽不直接引发CORS问题,但可能导致响应完整性异常。建议改为链式调用:

res.status(200).json({result:'success', userInfo: req.session.userInfo});

4. 预检请求处理顺序问题

确保app.options('*', cors(corsOptions))代码放在所有路由定义之前,否则预检请求可能无法被CORS中间件正确拦截处理。


内容的提问来源于stack exchange,提问作者Damiano Miazzi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 04:30:18