Vue 3 + Express代理服务器用户认证问题(CORS相关)
问题描述
我正在使用某API进行Vue 3与Express的开发测试,通过Postman和curl可正常访问接口,但Vue应用无法正常运行。经排查,代理服务器已与应用通信,在运行于http://localhost:8080/login的Vue应用提交登录请求时,已成功获取token并添加至Authorization请求头,但获取用户详情接口始终无法正常工作,怀疑是CORS问题导致。恳请各位提供帮助,谢谢。
代理服务器代码(proxy-server/server.js)
//proxy-server/server.js // Use Cors app.use(cors({ origin: 'http://localhost:8080', credentials: true, optionsSuccessStatus: 200 })); app.use(express.json()); app.get('/', (req, res) => { res.send('Hello, this is the proxy server!'); }); // Handle OPTIONS request for preflight checks app.options('/authentication', cors()); app.options('/users/me', cors()); app.get('/v2.1/authentication', cors(), async (req, res) => { try { const response = await axios.get('https://blood.arc.cubeapis.com/v2.1/authentication', { headers: req.headers, }); res.header('Access-Control-Allow-Origin', 'http://localhost:8080'); res.header('Access-Control-Allow-Credentials', 'true'); res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Origin, Content-Type, Access-Control-Request-Headers, Authorization'); res.header('Access-Control-Max-Age', '86400'); res.json(response.data); } catch (error) { console.error('Proxy Error:', error.message); res.status(500).json({ error: 'Internal Server Error located @ /v2.1/authentication' }); } }); app.post('/authentication', cors(), async (req, res) => { console.log('Received POST request:', req.method, req.url); console.log('Request headers:', req.headers); console.log('Request body:', req.body); try { const response = await axios.post('https://blood.arc.cubeapis.com/v2.1/authentication', req.body); res.header('Access-Control-Allow-Origin', 'http://localhost:8080'); res.header('Access-Control-Allow-Credentials', 'true'); res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Origin, Content-Type, Access-Control-Request-Headers, Authorization'); res.header('Access-Control-Max-Age', '86400'); res.json(response.data); } catch (error) { console.error('Proxy Error:', error.message); res.status(500).json({ error: 'Internal Server Error /authentication' }); } }); app.get('/users/me', cors(), async (req, res) => { console.log('Received GET request:', req.method, req.url); console.log('Request headers:', req.headers); console.log('Request body:', req.body); console.log('Forwarding to:', 'https://blood.arc.cubeapis.com' + req.url); try { const response = await axios.get('https://blood.arc.cubeapis.com/v2.1/users/me', { headers: req.headers, }); res.header('Access-Control-Allow-Origin', 'http://localhost:8080'); res.header('Access-Control-Allow-Credentials', 'true'); res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Origin, Content-Type, Access-Control-Request-Headers, Authorization'); res.header('Access-Control-Max-Age', '86400'); res.json(response.data); } catch (error) { console.error('Proxy Error:', error.message); res.status(500).json({ error: 'Internal Server Error /v2.1/users/me', details: error.message }); } });
解决方案
1. 移除重复的CORS配置
你已经通过app.use(cors({...}))做了全局CORS配置,不需要再给每个路由单独加cors()中间件,重复配置会导致头信息冲突。全局配置会自动处理OPTIONS预检请求,也不用单独写app.options路由。
2. 清理冗余响应头
全局CORS中间件会自动生成规范的响应头,无需在每个路由里重复用res.header设置,避免头信息重复或不符合浏览器校验规则。
3. 过滤不必要的请求头
转发请求到目标API时,host、origin这类头可能会被目标服务器拒绝,建议过滤后再转发:
const { host, origin, ...forwardHeaders } = req.headers; const response = await axios.get('https://blood.arc.cubeapis.com/v2.1/users/me', { headers: forwardHeaders, });
4. 确认Vue请求配置
Vue发送请求时必须开启withCredentials,否则浏览器不会携带凭证,和你的CORS配置匹配:
// Vue中axios请求示例 axios.get('/users/me', { withCredentials: true, headers: { 'Authorization': `Bearer ${token}` } })
修正后的代理服务器代码
//proxy-server/server.js const express = require('express'); const cors = require('cors'); const axios = require('axios'); const app = express(); // 全局CORS配置,覆盖所有路由 app.use(cors({ origin: 'http://localhost:8080', credentials: true, optionsSuccessStatus: 200, allowedHeaders: ['Origin', 'Content-Type', 'Authorization'], methods: ['GET', 'POST', 'OPTIONS'] })); app.use(express.json()); app.get('/', (req, res) => { res.send('Hello, this is the proxy server!'); }); app.get('/v2.1/authentication', async (req, res) => { try { const { host, origin, ...forwardHeaders } = req.headers; const response = await axios.get('https://blood.arc.cubeapis.com/v2.1/authentication', { headers: forwardHeaders, }); res.json(response.data); } catch (error) { console.error('Proxy Error:', error.message); res.status(500).json({ error: 'Internal Server Error located @ /v2.1/authentication' }); } }); app.post('/authentication', async (req, res) => { console.log('Received POST request:', req.method, req.url); console.log('Request headers:', req.headers); console.log('Request body:', req.body); try { const response = await axios.post('https://blood.arc.cubeapis.com/v2.1/authentication', req.body); res.json(response.data); } catch (error) { console.error('Proxy Error:', error.message); res.status(500).json({ error: 'Internal Server Error /authentication' }); } }); app.get('/users/me', async (req, res) => { console.log('Received GET request:', req.method, req.url); console.log('Request headers:', req.headers); console.log('Forwarding to:', 'https://blood.arc.cubeapis.com/v2.1/users/me'); try { const { host, origin, ...forwardHeaders } = req.headers; const response = await axios.get('https://blood.arc.cubeapis.com/v2.1/users/me', { headers: forwardHeaders, }); res.json(response.data); } catch (error) { console.error('Proxy Error:', error.message); res.status(500).json({ error: 'Internal Server Error /v2.1/users/me', details: error.message }); } }); // 启动服务器 const PORT = 3000; app.listen(PORT, () => { console.log(`Proxy server running on http://localhost:${PORT}`); });
内容的提问来源于stack exchange,提问作者dunkin
相关产品推荐
相关产品推荐

