在Firebase Functions中获取带Authorization Bearer请求的Token
看起来你碰到的问题其实是跨域预检请求在搞鬼!先给你拆解清楚,再一步步解决:
先分析你看到的请求头异常
从你打印的req.headers里有access-control-request-headers: authorization,content-type这一项,这说明你当前捕获到的是浏览器发送的OPTIONS预检请求,而不是真正的业务GET请求!
浏览器在发送跨域且携带自定义请求头(比如Authorization)的请求时,会先自动发送OPTIONS请求,用来确认服务器是否允许这些自定义头和请求方法。这个预检请求里是不会包含你实际的Authorization Token的——只有当服务器通过预检后,浏览器才会发送带Token的真实请求。这就是你找不到Bearer Token的核心原因!
一步步解决问题
1. 先处理CORS预检请求
你需要先让Express正确响应OPTIONS请求,允许前端的跨域请求和自定义头。最省心的方式是用cors库:
const functions = require('firebase-functions'); const express = require('express'); const cors = require('cors'); const app = express(); // 配置CORS,允许你的前端域名和Authorization头 app.use(cors({ origin: 'http://localhost:5000', // 替换成你的前端实际地址 allowedHeaders: ['Authorization', 'Content-Type'] })); // 如果你不想用cors库,也可以手动写OPTIONS处理逻辑: // app.options('*', (req, res) => { // res.set('Access-Control-Allow-Origin', 'http://localhost:5000'); // res.set('Access-Control-Allow-Headers', 'Authorization, Content-Type'); // res.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); // res.sendStatus(200); // });
2. 捕获并验证Token
处理完CORS后,真实请求的Authorization头就能正常传到函数里了。你可以用Firebase Admin SDK来验证Token,也可以手动解析:
const admin = require('firebase-admin'); admin.initializeApp(functions.config().firebase); // 自定义中间件:验证Token const verifyIdToken = async (req, res, next) => { const authHeader = req.headers.authorization; // 检查请求头格式是否正确 if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).send('Unauthorized: 未提供有效Token'); } // 提取Token const idToken = authHeader.split('Bearer ')[1]; try { // 用Firebase Admin验证Token const decodedToken = await admin.auth().verifyIdToken(idToken); req.user = decodedToken; // 把解析后的用户信息挂载到请求对象上 next(); // 验证通过,继续执行后续路由逻辑 } catch (error) { res.status(401).send('Unauthorized: Token无效'); } }; // 受保护的示例路由 app.get('/protected', verifyIdToken, (req, res) => { // 这里可以访问req.user获取用户UID等信息 res.send(`欢迎,用户 ${req.user.uid}!`); }); // 导出Firebase函数 exports.api = functions.https.onRequest(app);
3. 额外排查点
- 打开浏览器开发者工具的Network标签,确认是否有两次请求:先OPTIONS,再你要的GET请求。查看GET请求的Request Headers,确认Authorization头是否存在。
- 如果你之前用
express-bearer-token或express-authorization-bearer,要确保它们的挂载顺序在CORS中间件之后,不然预检请求会干扰Token解析。 - Node.js
v6.11.4虽然版本偏老,但处理请求头完全没问题,不用怀疑这个环节。
补充:前端正确获取Token的方式
你提到的示例代码过时问题是对的,现在前端获取Firebase ID Token的正确写法是:
firebase.auth().currentUser.getIdToken(true) // true表示强制刷新Token,避免过期 .then(idToken => { // 发送请求时带上Authorization头 fetch('http://localhost:5001/你的项目ID/api/protected', { method: 'GET', headers: { 'Authorization': `Bearer ${idToken}` } }); });
内容的提问来源于stack exchange,提问作者Franz Noel
相关产品推荐
相关产品推荐

