作为央国企科技子公司如何构建一套私有化的小程序开放平台:技术架构与平台治理实践

0 阅读12分钟

年初,团队接到一个非常庞大的需求:能不能把公司内部各个部门开发的工具类应用,以小程序的形式统一到一个APP里,让员工在一个入口找到所有内部工具,包括APP端和PC端,还要兼容信创系统。

现阶段公司内部已经上线了包括财务报销、考勤打卡、会议室预约、IT工单多个系统,很多系统都是不同软件供应商开发的,技术栈不同,用户体系不互通,体验割裂。特别是对于新入职的员工,记清楚这些平台入口都要专门培训一次;

初步评估了几条路径:H5嵌入、纯原生开发、小程序容器。前两条路径的共同问题是:每个系统各自维护一套用户体系,我们平台侧无法统一管控。小程序容器方案的核心优势在于:把各个系统的代码跑在统一的容器里,平台侧统一管理用户身份、权限、数据边界,各系统只需专注自己的业务实现。

考虑到后续的生态扩展,就要求这套技术不只服务于内部——将来可以向合作伙伴开放,以小程序形式接入更多外部服务,形成一个企业内部的小程序开放生态,后续无论哪一家供应商提供的服务,都可以以小程序的形式入驻,提供服务; 小程序平台架构图.png

二、技术架构——私有化部署的核心设计

2.1 整体架构

私有化部署模式下,整个平台分为三个层面:

运营管理层(管理后台)
  ├── 开发者管理(注册、认证、权限)
  ├── 内容审核(上下架、违规处理)
  └── 数据监控(访问量、错误率、安全审计)

运行时层(小程序容器 + SDK)
  └── 安全沙箱(每个小程序独立隔离运行)

宿主APP层(集成SDK的企业自有APP)

技术栈分两部分:服务端部署在企业私有服务器,所有数据不出内网;APP端集成小程序运行时 SDK,获得小程序运行能力,不需要依赖外部网络。

2.2 SDK初始化——双端代码

接入SDK是第一步。iOS和Android两端同时接入,接口协议一致,初始化代码量在40行以内。

iOS侧在AppDelegate中初始化:

// iOS SDK 初始化
// 来源:finclipdoc/runtime-sdk/ios/ios-integrate.md
NSMutableArray *storeArrayM = [NSMutableArray array];
FATStoreConfig *storeConfig = [[FATStoreConfig alloc] init];
storeConfig.sdkKey = @"您的sdkKey信息";
storeConfig.sdkSecret = @"您的sdkSecret信息";
storeConfig.apiServer = @"服务端地址";
[storeArrayM addObject:storeConfig];
[[FATClient sharedClient] initWithConfig:storeArrayM];

Android侧在Application中初始化,需要处理多进程隔离:小程序运行在独立进程中,宿主进程和第三方库初始化只在主进程执行:

// Android SDK 初始化——多进程处理
// 来源:finclipdoc/runtime-sdk/android/android-integrate.md
if (FinAppClient.INSTANCE.isFinAppProcess(this)) {
    // 小程序进程不执行任何初始化操作
    return;
}
List<FinStoreConfig> storeConfigs = new ArrayList<>();
FinStoreConfig config = new FinStoreConfig();
config.setSdkKey("您的sdkKey信息");
config.setSdkSecret("您的sdkSecret信息");
config.setApiServer("服务端地址");
storeConfigs.add(config);
FinAppClient.init(this, storeConfigs);
FinAppClient.start();

2.3 小程序启动与参数传递

企业内部各个系统通常需要携带员工身份信息(工号、部门、岗位角色)来控制可见内容和操作权限。SDK支持在启动小程序时传入自定义参数,参数由平台侧统一注入:

// Flutter 启动小程序——携带员工身份和权限参数
Future<Map> startApplet(RemoteAppletRequest request)

RemoteAppletRequest request = new RemoteAppletRequest(
  apiServer: 'https://私有化部署服务器地址/api',
  appletId: appId
);
request.startParams = {
  'empId': '员工工号',
  'dept': '部门',
  'role': '管理员/普通员工'
};
Mop.instance.startApplet(request);

2.4 安全沙箱——每个小程序独立隔离运行

基于对数据和权限的要求,每个入驻的小程序都运行在独立的安全沙箱里,代码无法访问宿主APP的内部数据,无法在用户不知情的情况下调用设备权限。

整个小程序的安全沙箱是三层隔离架构: sandbox-arch.png

第一层:进程级隔离。 每个小程序运行在独立进程中,和宿主APP主进程完全隔离。小程序崩溃不会影响APP主进程,APP主进程的问题也不会传导到小程序。进程级别的隔离是安全防护的基础。

第二层:权限管控层。 每个小程序在运行时只能访问manifest中声明的权限,比如地理位置、相机、存储等。用户在使用某个小程序之前会看到权限申请说明,授权记录在平台侧留存。没有声明的权限,小程序无法调用。这个机制保证了员工安装的每一个小程序,能做什么、不能做什么,都是平台侧可预期的。

第三层:数据边界层。 每个小程序有独立的存储空间,只能读写自己的数据区域,无法访问其他小程序的数据,也没法直接读取宿主APP的本地存储。企业敏感数据在这个层级得到保护。

安全沙箱的约束是代码层面的。如果小程序内部代码尝试绕过权限边界,平台会在运行时检测并阻止。

// Android 离线包启动——沙箱环境自动加载,无需额外配置
FinAppClient.appletApiManager.startApplet(
    this,
    IFinAppletRequest.Companion.fromAppId("https://私有化部署地址","小程序appId")
        .setOfflineParams("$filesDir/framework.zip", "$filesDir/小程序包.zip")
)

离线包在沙箱环境内自动解析和执行,平台侧可以在管理后台为每个离线包配置独立的运行策略。

三、平台治理——多租户隔离与权限管控

multi-tenant-arch.png

3.1 多租户模型

企业内部开放平台典型的角色结构是:平台运营方、各部门开发者、终端员工。

平台运营方拥有最高权限,可以创建租户、分配开发者账号、配置全局策略。各部门开发者在自己的租户内开发和发布小程序,只能看到自己租户内的数据,无法访问其他部门的小程序代码或用户数据。终端员工通过企业统一身份认证访问平台,看到的是平台侧配置好的小程序列表,和开发者账号完全隔离。

以财务部门入驻为例:财务部门申请成为平台开发者,在自己的租户内上传"报销助手"小程序,配置权限范围(仅财务部门员工可用)和数据策略。发布后,平台运营方审核通过,财务部门员工在APP里看到这个报销助手。人事部门或IT部门的开发者在自己租户内完全看不到财务部门的包体代码或访问数据。

3.2 开发者准入与认证

平台治理的第一步是管好谁能接入。我们建立了开发者准入机制:

实名认证:所有开发者必须通过企业统一身份认证注册,不接受个人账号接入企业级平台。

SDK授权:开发者在平台申请SDK使用时,平台侧分配带有约束的SDK凭证,这个凭证绑定到开发者账号和授权范围,不可跨账号使用。如果某个开发者账号出现违规行为,平台侧可以吊销其SDK授权,该开发者的小程序立即停止运行。

能力分级:不同级别的开发者获得不同的小程序能力。高权限开发者可以申请调用更多敏感API,比如获取员工详细信息的接口;普通开发者只能访问基础API。分级授权减少了权限滥用风险。

四、内容审核——上下架管理与运行时审计

4.1 上下架审核流程

平台侧建立了两级审核机制:上线前的内容审核和上线后的运行时监控。

上线前审核:开发者提交小程序包后,平台运营方审核代码包的安全性、权限声明的合理性、隐私政策的合规性。审核维度包括:是否声明了多余的权限、是否有数据外传行为、隐私协议是否合规。审核通过后小程序才会在员工端展示。

强制下架机制:如果某个小程序在运行过程中被发现有违规行为,平台侧可以在管理后台一键下架,不需要通知开发者,小程序立即从所有员工端消失。

4.2 运行时行为审计

安全沙箱不仅约束代码能做什么,也记录代码实际做了什么。

平台侧可以查看每个小程序的运行时行为日志,包括:尝试访问了哪些API、是否有异常的数据读写行为、崩溃和错误的详细记录。这些日志是企业内审和安全合规的必要依据,也是平台运营方发现违规行为的依据。

五、热更新与灰度发布——平台运营的日常

5.1 热更新机制

企业内部工具更新频率往往比外部APP高很多——社保规则调整、考勤政策变化、节假日排班更新,这些都需要小程序快速响应,不能等APP发版。

小程序容器模式把更新和发版解耦了:开发者在自己的租户内提交更新,平台审核通过后发布,用户下次打开时SDK自动拉取最新包。整个过程不需要APP重新发版,不需要员工手动更新,也不需要联系应用市场重新审核。

以"考勤打卡"小程序为例:公司在某个节假日调整了打卡规则,HR部门在后台提交更新,审核通过后发布,员工第二天打开考勤小程序,已经是最新规则。当月有两次政策调整,就发两次更新,不需要和APP发版捆绑在一起。

5.2 灰度发布

企业内部新功能上线,同样需要验证。平台侧支持按百分比、按部门、按员工角色灰度发布——先让一小部分员工试用新版,确认无问题后全量推开。对于考勤、报销这类涉及员工切身利益的功能,灰度发布是必要的稳定性保障。

六、私有化部署的关键考量

6.1 数据不出机房

私有化部署的核心意义在于数据合规。所有小程序的用户数据、访问日志、行为记录都存储在企业自有服务器,不经过任何外部网络。必须要求支持完整的私有化部署方案,支持部署在企业自有物理机房或私有云环境,不依赖公有云基础设施。

不仅是国央企,同样对于金融、政务、大型企业来说,这是基本要求。

6.2 信创支持——统信、麒麟、HarmonyOS

因为我们目前已经逐步在进行信创化改造,所以也对主流的信创进行兼容性测试:

  • 统信UOS:FinClip已完成适配,SDK可在统信系统上正常运行
  • 麒麟KylinOS:已通过兼容性测试,支持在麒麟系统环境中部署
  • HarmonyOS:支持HarmonyOS设备,可在鸿蒙生态内嵌小程序运行能力

七、需要关注的信息

平台建设成本不低。 搭建企业级小程序开放平台,不只是接一个SDK那么简单,还需要平台运营团队负责开发者准入审核、内容审核、安全监控、日常运维。中小型企业如果没有足够的运营资源,平台上线后会面临管理跟不上的问题。

开发者接入门槛需要控制。 内部各个部门的技术能力差异很大,有的部门有专业开发团队,有的部门只有业务人员。如果要求所有部门都按原生小程序标准开发,接入速度会很慢。可以提供小程序模板工具,让业务人员通过配置而非代码的方式快速创建小程序,降低初期接入门槛。

安全沙箱不等于业务安全。 安全沙箱解决了技术层面的数据隔离问题,但业务逻辑层面的权限控制需要小程序自己实现。比如某个小程序可以显示员工信息,但显示哪些字段、谁可以看,需要在小程序代码里做好判断,平台侧的安全沙箱管不到业务逻辑层面的访问控制。

八、常见问题总结

8.1 小程序在部分设备上无法加载,提示签名验证失败

现象:员工打开某个小程序,页面报错,显示签名验证失败。

原因:小程序包在传输或存储过程中被篡改,或者签名证书过期。

解决:在管理后台重新上传该小程序包,确保传输链路完整。检查签名证书有效期,过期证书需要重新签发。建议建立定期的包体完整性校验机制。

8.2 某部门的小程序更新后,部分员工看不到

现象:某部门发布了小程序更新,但部分员工打开还是旧版。

原因:这些员工设备的网络条件较差,SDK在后台静默下载时中断了,或者这些设备上的小程序缓存清理失败。

解决:在管理后台将该小程序设置为"强制更新",SDK下次检测到时会强制重新下载包体。对于网络条件差的场景,建议预先通过离线包预置最新版本。

8.3 平台如何处理小程序的违规行为

现象:某个小程序被员工举报存在数据收集行为异常。

原因:小程序在后台读取了超出其权限范围的数据,或者向外部服务器传输了用户信息。

解决:平台侧通过运行时行为审计日志定位问题后,立即在管理后台执行紧急下架,同时吊销该开发者账号的SDK授权。安全沙箱提供了技术层面的阻止能力,但运营层面的快速响应机制同样重要。


需要的话可以在Gitee中了解一下:Gitee Finclip