微前端子应用之间如何安全传递敏感数据?

综敏的笔记 阅读 14

在电商项目中,主应用需要把用户登录态传给子应用,现在用window.postMessage传递JSON数据,但发现其他子应用能监听到敏感字段,试过加token校验但还是不放心,有没有更安全的通信方案?

比如这样写主应用:

const data = { userId: 123, token: 'secret_token' };
parent.postMessage({ type: 'LOGIN', data }, '*');

子应用监听时:

window.addEventListener('message', (event) => {
  if (event.data.type === 'LOGIN') {
    console.log('获取到token:', event.data.data.token); // 其他应用也能看到这个日志
  }
});

这样直接透传token会不会太危险?有没有办法只让目标子应用接收数据?

我来解答 赞 3 收藏
二维码
手机扫码查看
2 条解答
开发者佼佼
这个问题我之前在做微前端项目的时候也踩过坑,当时也是被这个安全问题折腾得够呛。直接用 window.postMessage 确实方便,但安全性是个大问题,尤其是敏感数据像 token 这种东西,一旦被其他子应用监听到,后果很严重。

要解决这个问题,核心就是两点:限制消息的目标范围和对数据进行加密保护。

第一点,别再用 '*' 作为目标源了。你现在的代码里是这么写的:
parent.postMessage({ type: 'LOGIN', data }, '*');
这里的 '*' 表示任何页面都能接收到消息,这太危险了。改成明确的目标子应用的 URL,比如:
parent.postMessage({ type: 'LOGIN', data }, 'https://target-subapp.com');
这样就只有指定的子应用能接收到消息,其他子应用即使监听也没用。

第二点,加一层加密。token 这种敏感数据,建议在主应用发送前先加密一下,子应用收到后再解密。可以用简单的 AES 加密算法,比如借助 crypto-js 库。下面是改进后的代码:

主应用发送时:
const CryptoJS = require('crypto-js');
const secretKey = 'your-secret-key'; // 密钥一定要保管好

const data = { userId: 123, token: 'secret_token' };
const encryptedData = CryptoJS.AES.encrypt(JSON.stringify(data), secretKey).toString();

parent.postMessage({ type: 'LOGIN', data: encryptedData }, 'https://target-subapp.com');


子应用接收时:
const CryptoJS = require('crypto-js');
const secretKey = 'your-secret-key'; // 和主应用保持一致

window.addEventListener('message', (event) => {
if (event.origin !== 'https://main-app.com') return; // 验证来源
if (event.data.type === 'LOGIN') {
const decryptedData = CryptoJS.AES.decrypt(event.data.data, secretKey).toString(CryptoJS.enc.Utf8);
const parsedData = JSON.parse(decryptedData);
console.log('获取到token:', parsedData.token);
}
});


这里有几个细节要注意:
1. 密钥 secretKey 很重要,不要硬编码在代码里,最好通过环境变量或者后端动态下发。
2. 子应用收到消息后,一定要验证 event.origin 是不是可信的主应用地址,防止伪造消息攻击。
3. 如果你的项目有多个子应用需要通信,可以为每个子应用单独分配密钥,避免一个密钥泄露影响全局。

当时我也是折腾了好几天才把这套方案跑通,虽然看起来麻烦点,但安全性确实提升了不少。希望对你有帮助!
点赞
2026-02-20 02:03
Top丶东宇
做微前端通信时直接用postMessage确实方便,但安全性问题确实需要注意。一般这样处理:首先要限制消息的接收范围,别用通配符'*',改成指定目标子应用的origin。比如你的子应用部署在https://subapp.example.com,那就把targetOrigin改成这个地址。

主应用发送时可以这样写:
const data = { userId: 123, token: 'secret_token' };
parent.postMessage({ type: 'LOGIN', data }, 'https://subapp.example.com');

然后在接收端要做严格的校验,先判断来源是否合法:
window.addEventListener('message', (event) => {
if (event.origin !== 'https://mainapp.example.com') return;
// 这里再处理具体逻辑
});

但这还不够安全,建议对敏感数据做加密处理。可以在主应用和子应用之间约定一个共享密钥,用AES加密token等敏感信息。crypto-js库就挺好用的:

主应用加密:

import CryptoJS from 'crypto-js';
const secretKey = 'shared_secret_key';
const encrypted = CryptoJS.AES.encrypt(JSON.stringify(data), secretKey).toString();
parent.postMessage({ type: 'LOGIN', data: encrypted }, 'https://subapp.example.com');


子应用解密:

import CryptoJS from 'crypto-js';
const secretKey = 'shared_secret_key';
window.addEventListener('message', (event) => {
if (event.origin !== 'https://mainapp.example.com') return;
const bytes = CryptoJS.AES.decrypt(event.data.data, secretKey);
const decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
console.log('解密后的数据:', decryptedData);
});


最后提醒一下,密钥要妥善保管,最好通过环境变量注入,别直接写在代码里。这种方案基本能保证只有目标子应用能解密出真实数据,其他应用即使监听到也看不懂。当然,如果条件允许的话,走后端中台转发会更安全,不过实现起来会复杂一些。
点赞
2026-02-17 19:00