在項目開發中,若遇到在系統中內嵌其餘平臺頁面,可作參考。
(注:開發環境Angular8.1.0
,ng-zorro-antd:~8.0.2
,前端容器nginx:1.10.1
。)html
html
相應位置引入iframe
標籤,src
爲內嵌平臺的路徑。<iframe id="iframe" class="iframe-body" [src]="url" frameborder="0"\></iframe>
DomSanitizer
服務,獲取到iframe
元素後,經過postMessage
向內嵌平臺發送消息,獲取登陸權限。同時經過window.addEventListener
監聽內嵌系統是否鏈接成功,從而實現跨域通信。export class RemoteManagerComponent implements OnInit { constructor(private sanitizer: DomSanitizer) {} ngOnit() { this.url = this.sanitizer.bypassSecurityTrustResourceUrl(baseUrl + '/#/login'); this.postMessage(baseUrl); // baseUrl是http://:8080,即內嵌網頁的服務器地址 this.addListener(this.activeRoute); // activeRoute是內嵌頁面菜單路由 } // 向遠程發消息-受權 postMessage(baseUrl) { this.loading = true; let count = 10; this.time = setInterval(() => { let iframe = document.getElementById('iframe'); iframe['contentWindow'].postMessage('remote', baseUrl); if (count < 0) { clearInterval(this.time); this.time= null; this.notification.error('鏈接失敗,請重試', null); this.router.navigate(['路由']); } count--; }, 1000); } // 監聽遠程消息 addListener(activeRoute) { window.addEventListener('message', (e: any) => { clearInterval(this.time); this.time = null; switch (e.data) { case 'success': console.log('已受權'); document.getElementById('iframe')['src'] = activeRoute; this.url = this.sanitizer.bypassSecurityTrustResourceUrl(activeRoute); setTimeout(() => { this.loading = false; }, 2000); return; case 'failed': this.notification.error('鏈接失敗,請重試', null, {nzKey: 'failed'}); this.router.navigate(['路由']); return; case 'reboot': this.notification.error('鏈接已斷開,請從新鏈接', null, {nzKey: 'reboot'}); this.router.navigate(['路由']); return; default: break; } }, false); }
window.addEventListener
監聽遠程消息,接收到消息後經過window.parent.postMessage
向父頁面發送消息,代表已鏈接成功。// 監聽遠程管理-受權 addEventListener() { window.addEventListener('message', (e: any) => { if (e['source'] !== window.parent || e.data !== 'remote') { return; } this.storeService.save('remoteIp', e.origin); if (localStorage.getItem('isLogin')) { // 已受權 this.storeService.save('remoteHidden', true); window.parent.postMessage('success', e.origin); } else { // 未受權 this.configService.autoLogin({verifycode: 'soc_fw'}).subscribe((data: any) => { if (data.code === 200) { this.storeService.save('remoteHidden', true); localStorage.setItem('isLogin', 'true'); this.configService.whoAmI().then(() => { window.parent.postMessage('success', e.origin); }); } else { window.parent.postMessage('failed', e.origin); } }, () => { window.parent.postMessage('failed', e.origin); }); } }, false); }
服務器默認是不被容許跨域的,若遇到跨協議報錯等問題(如本系統爲http協議,內嵌系統爲https協議,會報403跨域錯誤 No 'Access-Control-Allow-Origin' header is present on the requested resource
),具體經過兩種方法解決:前端
location / { // 表示服務器能夠接受全部的請求源(Origin),即接受全部跨域的請求。 add_header Access-Control-Allow-Origin *; ………… }