Angular 15升级后iframe无法加载托管应用的问题求助
问题分析与解决方案
核心问题
报错里的X-Frame-Options: deny是被嵌入的Angular应用(https://www.uat.com)返回的响应头,不是你CMS发送请求时携带的头。你之前在HttpHeaders里添加的配置完全无效——因为控制iframe嵌入权限的是目标站点(uat.com)的响应头,而非CMS的请求头。
正确解决步骤
你需要在被嵌入的Angular 15项目的服务器配置中添加允许嵌入的响应头,分以下场景处理:
1. 本地开发(Angular CLI dev-server)
修改angular.json中serve节点的配置,添加响应头:
"projects": { "your-project-name": { "architect": { "serve": { "builder": "@angular-devkit/build-angular:dev-server", "options": { "headers": { "X-Frame-Options": "SAMEORIGIN", // 同域名嵌入允许,跨域场景优先用CSP "Content-Security-Policy": "frame-src 'self' https://你的CMS域名;" } } } } } }
2. 生产环境(Nginx托管)
在Nginx的站点配置文件中添加响应头:
server { listen 443 ssl; server_name www.uat.com; # 允许指定域名嵌入iframe add_header X-Frame-Options SAMEORIGIN; add_header Content-Security-Policy "frame-src 'self' https://你的CMS域名;"; # 其他Nginx配置项... }
3. Angular Universal(SSR)
在server.ts中修改响应头:
import { APP_BASE_HREF } from '@angular/common'; import { ngExpressEngine } from '@nguniversal/express-engine'; import * as express from 'express'; import { existsSync } from 'fs'; import { join } from 'path'; const app = express(); const distFolder = join(process.cwd(), 'dist/your-project/browser'); const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index'; app.engine('html', ngExpressEngine({ bootstrap: AppServerModule, })); app.set('view engine', 'html'); app.set('views', distFolder); app.get('*', (req, res) => { // 添加允许嵌入的响应头 res.setHeader('X-Frame-Options', 'SAMEORIGIN'); res.setHeader('Content-Security-Policy', 'frame-src 'self' https://你的CMS域名;'); res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] }); }); // 其他SSR配置项...
关键注意事项
- 如果CMS和uat.com是不同域名,优先使用
Content-Security-Policy的frame-src指定允许的CMS域名,因为X-Frame-Options的ALLOW-FROM已被多数浏览器废弃。 - 修改配置后必须清除浏览器缓存或强制刷新(Ctrl+F5),避免旧的响应头缓存影响测试结果。
- 验证配置生效:通过浏览器开发者工具的「网络」面板,查看uat.com的响应头是否包含正确的
X-Frame-Options或Content-Security-Policy。
内容的提问来源于stack exchange,提问作者HARI PRASAD
相关产品推荐
相关产品推荐

