DataWorks Embed API - 手把手教您在自建的 Web 嵌入 DataWorks 数据血缘图

简介: DataWorks 提供丰富的数据可视化界面,让用户能轻松地透过界面操作大数据业务,但仍有集成至自建 Web 界面的需求,减少切换页面的频率。下文就以透过阿里云令牌服务结合自建 Web 界面代理登录阿里云,做到嵌入DataWorks数据地图的血缘图。

前言

DataWorks 提供丰富的数据可视化界面,让用户能轻松地透过界面操作大数据业务,但仍有集成至自建 Web 界面的需求,减少切换页面的频率。DataWorks 新推出的 Embed API 透过阿里云令牌服务结合自建 Web 界面代理登录阿里云,做到嵌入DataWorks数据地图的血缘图。


Embed API https://dataworks.data.aliyun.com/cn-shanghai/open/playground/case?id=dataLineageGraph


先看效果图

image.png



登录态处理


登录态的处理有五个方面要处理

  • RAM 帐号
  • 代理 Role
  • 获取临时 AK
  • 获取登录 Token
  • 嵌入页面


其顺序图如下:



RAM 帐号

打开 RAM 访问控制,建立一个 RAM 帐号,并赋予 AliyunSTSAssumeRoleAccess 权限 (使此 RAM 帐号有代理 Role 的权限),以及取得 RAM 帐号的 AK,我们将在自建 Web 里使用这个 RAM 帐号登录获取临时 AK。


若使用 Open API 来新建可参考以下页面:


安全提示: 建议在自建 Web 里,其自运维的用户帐号一对一对应到一个阿里云的 RAM 帐号或 Role,例如自建的 LDAP 系统,每新建一个帐号就自动绑定一个阿里云 RAM 帐号或 Role,并且是一对一的关系不使用共享一个帐号或 Role 的方式


代理 Role

取得 RAM 帐号的 AK 后,使用这个 RAM 来代理一个 Role 并取得临时 AK,打开角色页面,建立一个角色,并取得这个角色的 ARN 码。


若使用 Open API 来新建可参考以下页面:


获取临时 AK

取得角色 ARN 码后,我们已俱备以下信息:

  • RAM 帐号 AK (AccessKeyId, AccessKeySecret)
  • Role ARN
  • 要登录的 DataWorks 的地域 (如上海为 cn-shanghai)


使用 STS 获取临时 AK 的 Open API 接口,接口描述查看


透过此接口我们可取到以下信息:

  • 临时 AK (AccessKeyId, AccessKeySecret)
  • securityToken (安全令牌)


获取登录 Token


取得临时 AK 与安全令牌后,再透过阿里云登录服务 ( signin.aliyun.com/federation ),取得 SigninToken (登录令牌),如以下代码示例。

// get aliyun signing token
const signingUrl = 'https://signin.aliyun.com/federation';
const params = new URLSearchParams();
params.append('Action', 'GetSigninToken');
params.append('AccessKeyId', accessKeyId); // 临时 accessKeyId
params.append('AccessKeySecret', accessKeySecret); // 临时 accessKeySecret
params.append('SecurityToken', securityToken); // 安全令牌
params.append('TicketType', 'mini');
const signingResult = await fetch(signingUrl, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  body: params,
});
const result = await signingResult?.json?.();
console.log(result?.SigninToken);


嵌入页面

取得登录令牌后,组织以下路径,透过 iframe 嵌入即可使用 DataWorks 血缘图。


https://signin.aliyun.com/federation?Action=Login&LoginUrl=${encodedLoginUrl}&Destination=${encodedUrl}&SigninToken=${encodedSinginToken} 


参数说明:

  • encodedLoginUrl: 为登录态失效后的转登页面,通常为 https://signin.aliyun.com
  • encodedUrl: 为最终使用 DataWorks 的界面链接,此处需要 DataWorks 提供可嵌入使用的功能链接。
  • encodedSinginToken: 登录令牌


参考代码

代码范例 (以Node.js为例)


  • index.js
const express = require('express');
const path = require('path');
const LoginAliyun = require('./loginAliyun');
const fetch = require('node-fetch');
const fs = require('fs');
const http = require('http');
const https = require('https');
const privateKey = fs.readFileSync('./sslcert/example.com.key', 'utf8');
const certificate = fs.readFileSync('./sslcert/example.com.crt', 'utf8');

const credentials = { key: privateKey, cert: certificate };

const app = express();

// Have Node serve the files for our built React app
app.use(express.static(path.resolve(__dirname, './client/dist')));

app.get("/getSigninToken", async (req, res) => {

  const regionId = 'cn-shanghai';
  const ramAccessKeyId = 'your ram access key id';
  const ramAccessKeySecret = 'your ram access key secret';
  const roleArn = 'role arn';

  const loginResult = await LoginAliyun.main(ramAccessKeyId, ramAccessKeySecret, regionId, roleArn);
  const credentials = loginResult?.body?.credentials;

  if (!credentials) {
    res.json({ message: 'error' });
    return;
  }

  // const { arn, assumedRoleUser } = loginResult?.body?.assumedRoleUser || {};
  const { accessKeyId, accessKeySecret, securityToken, expiration } = credentials || {};

  // get aliyun signing token
  const signingUrl = 'https://signin.aliyun.com/federation';

  const params = new URLSearchParams();
  params.append('Action', 'GetSigninToken');
  params.append('AccessKeyId', accessKeyId);
  params.append('AccessKeySecret', accessKeySecret);
  params.append('SecurityToken', securityToken);
  params.append('TicketType', 'mini');

  const signingResult = await fetch(signingUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: params,
  });

  const result = await signingResult?.json?.();

  res.json({ data: result?.SigninToken || '' });
});

// All other GET requests not handled before will return our React app
app.get('*', (req, res) => {
  res.sendFile(path.resolve(__dirname, './client/dist', 'index.html'));
});

const httpServer = http.createServer(app);
const httpsServer = https.createServer(credentials, app);

httpServer.listen(8080);
httpsServer.listen(8443);

console.log('express running at http://localhost:%d', 8080);
  • loginAliyun.js
'use strict';
// This file is auto-generated, don't edit it
// 依赖的模块可通过下载工程中的模块依赖文件或右上角的获取 SDK 依赖信息查看
const Sts20150401 = require('@alicloud/sts20150401');
const OpenApi = require('@alicloud/openapi-client');
const Util = require('@alicloud/tea-util');
const Tea = require('@alicloud/tea-typescript');

// https://api.aliyun.com/api/Sts/2015-04-01/AssumeRole?lang=NODEJS
class Client {

  /**
   * 使用AK&SK初始化账号Client
   * @return Client
   * @throws Exception
   */
  static createClient(accessKeyId, accessKeySecret, regionId) {
    // 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。
    // 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378664.html。
    let config = new OpenApi.Config({
      // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
      accessKeyId: process.env['ALIBABA_CLOUD_ACCESS_KEY_ID'] || accessKeyId,
      // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
      accessKeySecret: process.env['ALIBABA_CLOUD_ACCESS_KEY_SECRET'] || accessKeySecret,
    });
    // Endpoint 请参考 https://api.aliyun.com/product/Sts
    config.endpoint = `sts.${regionId}.aliyuncs.com`;
    return new Sts20150401.default(config);
  }

  static async main(accessKeyId, accessKeySecret, regionId, roleArn, roleSessionName, durationSeconds) {
    let result;
    let client = Client.createClient(accessKeyId, accessKeySecret, regionId);
    let assumeRoleRequest = new Sts20150401.AssumeRoleRequest({
      roleArn: roleArn,
      roleSessionName: roleSessionName || 'ram',
      durationSeconds: durationSeconds || 3600, // 有效期,单位为秒
    });
    let runtime = new Util.RuntimeOptions({});
    try {
      // 复制代码运行请自行打印 API 的返回值
      result = await client.assumeRoleWithOptions(assumeRoleRequest, runtime);
    } catch (error) {
      // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
      // 错误 message
      console.log(error.message);
      // 诊断地址
      console.log(error.data["Recommend"]);
      Util.default.assertAsString(error.message);
    }
    return result;
  }

}

module.exports = Client;


  • package.json
{
  "name": "aliyun-iframe-dataworks-server",
  "version": "1.0.0",
  "description": "Aliyun Iframe DataWorks",
  "private": true,
  "main": "/pages/index.html",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "@alicloud/openapi-client": "0.4.7",
    "@alicloud/sts20150401": "1.1.3",
    "@alicloud/tea-typescript": "1.8.0",
    "@alicloud/tea-util": "1.4.7",
    "express": "4.17.1",
    "node-fetch": "2.7.0",
    "path": "^0.12.7"
  },
  "engines": {
    "node": ">=16.16.0"
  }
}


  • client/dist/index.html
<!DOCTYPE html>

<head>
  <style>
    #url-input {
      width: 600px;
    }

    iframe {
      margin: 16px;
      width: calc(100% - 32px);
      height: 680px;
    }
  </style>
  <script>
    window.fetchSigninToken = async () => {
      let result = '';
      try {
        const response = await fetch('/getSigninToken');
        const json = await response?.json?.();
        result = json?.data;
      } catch (e) {
        console.error(e);
      }
      return result;
    };
    window.onUrlChange = async () => {
      try {
        const url = document.getElementById('url-input').value;
        if (!url) return;
        const signinToken = await fetchSigninToken();
        if (!signinToken) return;
        const encodedLoginUrl = encodeURIComponent('https://signin.aliyun.com');
        const encodedUrl = encodeURIComponent(url);
        const encodedSinginToken = encodeURIComponent(signinToken);
        const iframe = document.getElementById('iframe-web');
        iframe.src = `https://signin.aliyun.com/federation?Action=Login&LoginUrl=${encodedLoginUrl}&Destination=${encodedUrl}&SigninToken=${encodedSinginToken}`;
      } catch (e) {
        console.error(e);
      }
    };
  </script>
</head>

<body>
  <div id="message"></div>
  嵌入的页面:
  <span>URL: </span><input id="url-input" type="text" />
  <button onclick="onUrlChange();">刷新</button>
  <div>
    <iframe id="iframe-web" frameBorder="0"></iframe>
  </div>
</body>


  • sslcert 文件夹下新建 example.com.crt 与 example.com.key


修改 index.js 以下部份:


const regionId = 'cn-shanghai'; // 要登录 DataWorks 的地域
const ramAccessKeyId = 'your ram access key id'; // RAM 帐户的 Access Key Id
const ramAccessKeySecret = 'your ram access key secret'; // RAM 帐户的 Access Key Secret
const roleArn = 'role arn'; // 角色 ARN



执行以下指令:

yarn install # 安装依赖
yarn start


打开路径 https://localhost:8443/,并填入要嵌入的页面链接

image.png



小结与后续

STS 令牌服务登录业务是阿里云提供的嵌入方式,其它业务如 OpenTelemetry、嵌入管控台也都是使用此方法,但使用此方法后,仍有一些问题需要解决:


  • 被嵌入的业务方,需提供可嵌入的功能模块、链接格式、可提供的参数透出给接入方
  • 被嵌入的业务模块,需要隐藏如公共头、侧边栏以及不必要的跳转,也需要被嵌入的业务方来调整
  • 当使用 RAM 帐号透过 STS 令牌服务登录 DataWorks 后,若单独打开 DataWorks 链接也会是登录状态,其原因是因为 STS 令牌服务的登录失效时间与 DataWorks 登录失效时间不一致导致,后续若统一调整为阿里云登录失效时间后,此问题可解
  • 虽然我们只给 RAM 帐号 AliyunSTSAssumeRoleAccess 的权限,但是仍需要接入方在自建的 Web 系统上,将自营的帐号一对一对应到 RAM 帐号或 Role,让每个登录到自建的 Web 的用户,都是独立使用一个 RAM 帐号或 Role (不使用共享一个帐号或 Role 的方式),提高安全性
  • 确保每次都能完整初始化 DataWorks 页面,可在背景 (隐藏 iframe) 先嵌入完整页面如 https://dataworks4service.data.aliyun.com/cn-shanghai/dmc,再将 iframe 链接调整至功能模块 (血缘图)




相关实践学习
基于Hologres轻量实时的高性能OLAP分析
本教程基于GitHub Archive公开数据集,通过DataWorks将GitHub中的项⽬、行为等20多种事件类型数据实时采集至Hologres进行分析,同时使用DataV内置模板,快速搭建实时可视化数据大屏,从开发者、项⽬、编程语⾔等多个维度了解GitHub实时数据变化情况。
目录
相关文章
|
5月前
|
JSON 缓存 算法
如何通过API获取1688商品类目数据:技术实现指南
1688开放平台提供alibaba.category.get接口,支持获取全量商品类目树。RESTful架构,返回JSON数据,含类目ID、名称、层级等信息。需注册账号、创建应用并授权。请求需签名认证,QPS限10次,建议缓存更新周期≥24小时。
483 2
|
5月前
|
JSON 安全 API
亚马逊商品列表API秘籍!轻松获取商品列表数据
亚马逊商品列表API(SP-API)提供标准化接口,支持通过关键词、分类、价格等条件搜索商品,获取ASIN、价格、销量等信息。采用OAuth 2.0认证与AWS签名,保障安全。数据以JSON格式传输,便于开发者批量获取与分析。
|
5月前
|
JSON 监控 API
小红书笔记评论API:一键获取分层评论与用户互动数据
小红书笔记评论API可获取指定笔记的评论详情,包括内容、点赞数、评论者信息等,支持分页与身份认证,返回JSON格式数据,适用于舆情监控、用户行为分析等场景。
|
6月前
|
供应链 监控 安全
1688商品详情API接口实战指南:合规获取数据,驱动B2B业务增长
1688商品详情API(alibaba.product.get)是合规获取B2B商品数据的核心工具,支持全维度信息调用,助力企业实现智能选品、供应链优化与市场洞察,推动数字化转型。
|
5月前
|
数据采集 JSON API
微店API使用指南:高效获取商品列表数据
本文介绍如何使用Python爬虫调用微店item_search接口,根据关键词搜索商品并获取商品列表数据,涵盖请求方式、JSON数据解析、分页参数设置及筛选排序功能,适用于电商数据分析与竞品研究。
|
5月前
|
JSON API 数据格式
淘宝拍立淘按图搜索API系列,json数据返回
淘宝拍立淘按图搜索API系列通过图像识别技术实现商品搜索功能,调用后返回的JSON数据包含商品标题、图片链接、价格、销量、相似度评分等核心字段,支持分页和详细商品信息展示。以下是该API接口返回的JSON数据示例及详细解析:
|
5月前
|
JSON 算法 API
Python采集淘宝商品评论API接口及JSON数据返回全程指南
Python采集淘宝商品评论API接口及JSON数据返回全程指南
|
5月前
|
自然语言处理 算法 数据可视化
看球总刷比分?好奇数据哪来的?你该认识一下「体育API」了
体育API是赛事数据的“幕后搬运工”,实时同步比分、赛程、球员统计等信息,支撑各类应用提供精准推送、深度分析与互动体验,让观赛更智能高效。
496 150
|
5月前
|
JSON API 数据安全/隐私保护
Python采集淘宝拍立淘按图搜索API接口及JSON数据返回全流程指南
通过以上流程,可实现淘宝拍立淘按图搜索的完整调用链路,并获取结构化的JSON商品数据,支撑电商比价、智能推荐等业务场景。
|
6月前
|
JSON 前端开发 API
如何调用体育数据足篮接口API
本文介绍如何调用体育数据API:首先选择可靠服务商并注册获取密钥,接着阅读文档了解基础URL、端点、参数及请求头,然后使用Python等语言发送请求、解析JSON数据,最后将数据应用于Web、App或分析场景,同时注意密钥安全、速率限制与错误处理。
683 152

相关产品

  • 大数据开发治理平台 DataWorks