Angular 5拦截器未正确发送JWT请求头,后端验证失败求助
解决Angular 5拦截器添加JWT Token后后端返回403的问题
你遇到的核心问题是浏览器CORS预检请求(OPTIONS)和后端JWT验证逻辑的冲突,结合你的代码细节,我来一步步拆解解决方案:
问题根源分析
- OPTIONS请求不携带自定义头:浏览器在发送跨域的POST/GET等请求前,会自动发起OPTIONS预检请求,用来确认服务器是否允许该跨域请求。这个预检请求不会携带你通过拦截器添加的
x-access-token头。 - 后端对OPTIONS请求也做了Token验证:你的后端中间件对所有进入的请求都执行了Token检查,当OPTIONS请求进来时,因为没有Token,直接返回了403错误,导致后续真实请求根本没机会发送。
解决方案步骤
1. 修改后端中间件,放行OPTIONS预检请求
首先要让后端跳过对OPTIONS请求的Token验证,直接放行。修改你的后端中间件代码:
router.use(function(req,res,next){ // 优先处理OPTIONS预检请求,直接返回200 if (req.method === 'OPTIONS') { return res.sendStatus(200); } // 日志记录 console.log('Somebody just came to our app!'); console.log(req.headers); // 检查请求体、URL参数或请求头中的token var token = req.body.token || req.query.token || req.headers['x-access-token']; // 解码token if (token) { // 验证密钥并检查过期时间 jwt.verify(token, superSecret, function(err, decoded) { if (err) { return res.json({ success: false, message: 'Failed to authenticate token.' }); } else { // 验证通过,保存到请求对象供后续路由使用 req.decoded = decoded; next(); // 确保进入下一路由,不中断 } }); } else { // 无token时,返回403禁止访问响应及错误信息 return res.status(403).send({ success: false, message: 'No token provided.' }); } });
2. 修正前端拦截器,确保正确获取并添加Token
你之前的拦截器用了硬编码的headerValue,实际应该从用户登录后的存储(比如localStorage)中获取真实的JWT Token,同时优化错误处理逻辑(Angular 5推荐使用pipe+catchError替代旧的.catch):
import { throwError } from 'rxjs'; import { catchError } from 'rxjs/operators'; intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { console.log("intercepted request ... "); // 从localStorage获取用户登录后存储的Token const authToken = localStorage.getItem('userToken'); let authReq = req; // 仅当Token存在时,才添加请求头 if (authToken) { // 克隆请求并添加x-access-token头 authReq = req.clone({ headers: req.headers.set('x-access-token', authToken) }); console.log("Sending request with auth header now ..."); console.log(authReq.headers); } // 发送处理后的请求,并捕获错误 return next.handle(authReq) .pipe( catchError((error) => { console.log("Error Occurred"); console.log(error); // 将错误抛回给调用方处理 return throwError(() => error); }) ); }
3. 额外检查点
- 确认后端CORS配置允许
x-access-token头:如果后端用了CORS中间件(比如cors包),需要显式配置允许自定义头,例如:const corsOptions = { allowedHeaders: ['Content-Type', 'x-access-token'] }; router.use(cors(corsOptions)); - 检查浏览器Network面板:查看真实请求(非OPTIONS)的Request Headers中是否包含
x-access-token,确认Token值正确。 - 验证Token有效性:确保存储在localStorage中的Token未过期、未被篡改。
内容的提问来源于stack exchange,提问作者Uriel Parienti
相关产品推荐
相关产品推荐

