跨域资源共享(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
相关产品推荐
相关产品推荐

