如何避免Express.js认证中间件捕获HTTP OPTIONS请求
解决Express认证中间件拦截OPTIONS预请求的问题
我之前也碰到过一模一样的坑!浏览器发送的OPTIONS预请求(也就是CORS预检请求)本来就不会带Authorization头,所以咱们的认证中间件得先把这类请求直接放行,别拦着。下面给你两个实用的解决办法:
方法一:在自定义认证中间件里跳过OPTIONS请求
最简单直接的方式,就是在你的认证中间件开头加个判断——如果请求方法是OPTIONS,就直接调用next()让它通过:
// 你的自定义认证中间件 const authMiddleware = (req, res, next) => { // 先放行OPTIONS预请求 if (req.method === 'OPTIONS') { return next(); } // 下面是你原本的认证逻辑 const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ message: 'Unauthorized' }); } const token = authHeader.split(' ')[1]; // 这里写你的token验证逻辑,比如用jsonwebtoken的verify方法 // ... next(); }; // 把中间件挂载到需要权限验证的路由上 app.use('/api/protected', authMiddleware);
方法二:用cors包自动处理预检请求
如果你的项目还没配置跨域,推荐直接用官方的cors npm包,它会自动帮你处理OPTIONS预请求,不用自己写判断逻辑,省心很多:
首先安装依赖:
npm install cors
然后在Express应用里配置:
const cors = require('cors'); // 配置CORS,允许你的Angular应用域名,同时放行Authorization头 app.use(cors({ origin: 'http://your-angular-app-domain.com', // 替换成你的Angular实际域名 allowedHeaders: ['Authorization', 'Content-Type'], credentials: true // 如果需要携带cookie就开启,不需要可以删掉 })); // 之后再挂载你的认证中间件 app.use('/api/protected', authMiddleware);
这个方法的优势在于,cors包会自动响应OPTIONS请求并返回正确的CORS头,而且不会触发你的认证中间件,从根源上避免了拦截问题。
补充:为什么会出现这个问题?
浏览器的同源策略规定,当前端发送跨域复杂请求(比如带自定义头的GET请求)时,会先发送一个OPTIONS预请求,用来询问服务器是否允许这个跨域请求。这个预请求不会携带任何自定义头(包括Authorization),所以如果咱们的认证中间件没做特殊处理,就会把它当成未授权请求拦截掉,导致实际的GET请求根本没机会发送。
另外你的Angular请求代码是没问题的,它确实在实际GET请求里带了Authorization头,只要解决了OPTIONS的拦截问题,就能正常请求接口啦。
内容的提问来源于stack exchange,提问作者Ramy Farid
相关产品推荐
相关产品推荐

