You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 16跨域跳转双向JSON传参架构方案咨询

跨域站点间JSON传递与回调的标准实现(Angular 16)

针对你描述的a.com与B.com跨域JSON传递、处理后回调的场景,结合已实现SSO的前提,有两种成熟的标准方案,分别适配不同数据规模需求:

方案1:URL查询参数(适合小体积JSON)

适用场景:JSON数据体积小(通常≤2KB)、无敏感信息
核心逻辑:将JSON编码后通过URL查询参数传递,跳转完成后同样通过URL参数回调结果

  • a.com生成JSON后转为Base64编码(避免特殊字符干扰URL解析),携带参数跳转至B.com
  • B.com解析URL参数还原原始JSON,处理报表后生成新JSON,编码后跳转回a.com指定回调路由
  • a.com解析回调URL的参数获取最终结果

方案2:共享后端存储(适合大体积/敏感JSON)

适用场景:JSON数据体积大、包含敏感信息
核心逻辑:利用SSO提供的用户身份,结合共享存储(如Redis、数据库)通过唯一ID传递数据

  • a.com生成唯一ID(如UUID),将JSON存入共享存储并关联当前用户ID,跳转B.com时携带该ID
  • B.com通过SSO获取用户ID,用唯一ID从存储中读取JSON,处理后将新JSON存入同一ID(或新ID),跳转回a.com并携带结果ID
  • a.com用结果ID读取新JSON,完成后清理存储数据避免冗余

Angular 16 示例代码

方案1:a.com 发送数据并跳转

import { Component } from '@angular/core';

@Component({
  selector: 'app-report-trigger',
  template: '<button (click)="navigateToReportSite()">生成报表</button>'
})
export class ReportTriggerComponent {
  navigateToReportSite() {
    // 模拟用户选择生成的JSON数据
    const userPayload = {
      selectedItems: ['item1', 'item3'],
      dateRange: { start: '2024-01-01', end: '2024-01-31' }
    };
    // JSON转Base64编码
    const encodedPayload = btoa(JSON.stringify(userPayload));
    // 跳转至B.com报表页面
    window.location.href = `https://b.com/report?payload=${encodedPayload}`;
  }
}

方案1:B.com 接收数据并回调

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-report-processor',
  template: '<div>报表处理中,请稍候...</div>'
})
export class ReportProcessorComponent implements OnInit {
  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    this.route.queryParams.subscribe(params => {
      const encodedPayload = params['payload'];
      if (encodedPayload) {
        // 解码还原原始JSON
        const originalData = JSON.parse(atob(encodedPayload));
        // 模拟报表处理逻辑,生成结果JSON
        const reportResult = {
          ...originalData,
          reportId: 'REP-2024-007',
          status: 'success',
          data: [/* 报表数据 */]
        };
        // 编码结果并回调a.com
        const encodedResult = btoa(JSON.stringify(reportResult));
        window.location.href = `https://a.com/report-result?result=${encodedResult}`;
      }
    });
  }
}

方案1:a.com 接收回调结果

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-report-result',
  template: '<div>报表结果:{{reportResult | json}}</div>'
})
export class ReportResultComponent implements OnInit {
  reportResult: any;

  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    this.route.queryParams.subscribe(params => {
      const encodedResult = params['result'];
      if (encodedResult) {
        this.reportResult = JSON.parse(atob(encodedResult));
      }
    });
  }
}

方案2:a.com 存入共享存储并跳转

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { v4 as uuidv4 } from 'uuid'; // 需安装依赖:npm install uuid @types/uuid

@Component({
  selector: 'app-report-trigger',
  template: '<button (click)="navigateToReportSite()">生成报表</button>'
})
export class ReportTriggerComponent {
  constructor(private http: HttpClient) {}

  async navigateToReportSite() {
    const userPayload = {
      selectedItems: ['item1', 'item3'],
      dateRange: { start: '2024-01-01', end: '2024-01-31' }
    };
    const dataId = uuidv4();
    const userId = this.extractUserIdFromSSO();

    // 将数据存入共享后端存储
    await this.http.post('/api/shared-storage', {
      dataId,
      userId,
      data: userPayload
    }).toPromise();

    // 跳转至B.com并携带dataId
    window.location.href = `https://b.com/report?dataId=${dataId}`;
  }

  // 从SSO Token中解析用户ID(示例逻辑,需匹配你的SSO实现)
  private extractUserIdFromSSO(): string {
    const ssoToken = localStorage.getItem('sso_token');
    return ssoToken ? JSON.parse(atob(ssoToken.split('.')[1])).sub : '';
  }
}

方案2:B.com 读取数据并回调

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, HttpClient } from '@angular/router';

@Component({
  selector: 'app-report-processor',
  template: '<div>报表处理中,请稍候...</div>'
})
export class ReportProcessorComponent implements OnInit {
  constructor(private route: ActivatedRoute, private http: HttpClient) {}

  async ngOnInit() {
    this.route.queryParams.subscribe(async params => {
      const dataId = params['dataId'];
      if (dataId) {
        const userId = this.extractUserIdFromSSO();
        // 从共享存储读取原始数据
        const response = await this.http.get(`/api/shared-storage/${dataId}?userId=${userId}`).toPromise();
        const originalData = (response as any).data;

        // 模拟报表处理生成结果
        const reportResult = {
          ...originalData,
          reportId: 'REP-2024-007',
          status: 'success',
          data: [/* 报表数据 */]
        };

        // 将结果存入共享存储
        await this.http.put(`/api/shared-storage/${dataId}`, {
          userId,
          data: reportResult
        }).toPromise();

        // 回调a.com并携带dataId
        window.location.href = `https://a.com/report-result?resultId=${dataId}`;
      }
    });
  }

  private extractUserIdFromSSO(): string {
    const ssoToken = localStorage.getItem('sso_token');
    return ssoToken ? JSON.parse(atob(ssoToken.split('.')[1])).sub : '';
  }
}

方案2:a.com 读取结果并清理存储

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, HttpClient } from '@angular/router';

@Component({
  selector: 'app-report-result',
  template: '<div>报表结果:{{reportResult | json}}</div>'
})
export class ReportResultComponent implements OnInit {
  reportResult: any;

  constructor(private route: ActivatedRoute, private http: HttpClient) {}

  async ngOnInit() {
    this.route.queryParams.subscribe(async params => {
      const resultId = params['resultId'];
      if (resultId) {
        const userId = this.extractUserIdFromSSO();
        // 读取结果数据
        const response = await this.http.get(`/api/shared-storage/${resultId}?userId=${userId}`).toPromise();
        this.reportResult = (response as any).data;

        // 清理共享存储中的数据
        await this.http.delete(`/api/shared-storage/${resultId}?userId=${userId}`).toPromise();
      }
    });
  }

  private extractUserIdFromSSO(): string {
    const ssoToken = localStorage.getItem('sso_token');
    return ssoToken ? JSON.parse(atob(ssoToken.split('.')[1])).sub : '';
  }
}

关键注意事项

  • URL参数方案需注意Base64编码后的总长度,超过浏览器URL限制(通常2KB)会导致数据截断,大体积数据优先选择共享存储方案
  • 共享存储方案需添加数据过期机制,避免存储冗余;同时基于SSO用户ID做权限校验,防止数据越权访问
  • 跳转前需确认SSO会话有效,避免用户需重新登录

内容的提问来源于stack exchange,提问作者Azure-Core

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 12:28:17