first commit
This commit is contained in:
1659
concept.MDX
Normal file
1659
concept.MDX
Normal file
File diff suppressed because it is too large
Load Diff
136
concept.txt
Normal file
136
concept.txt
Normal file
@@ -0,0 +1,136 @@
|
||||
Tài liệu khái niệm: Kiến trúc SuperApp Runtime Modularization với Cơ chế Bảo Mật
|
||||
|
||||
1. Mục tiêu
|
||||
Xây dựng một ứng dụng SuperApp trên nền tảng Flutter (iOS và Android) có khả năng tải và chạy các SubApp từ xa thông qua WebView tại thời điểm runtime. Mỗi SubApp nằm trong một repository riêng, được triển khai dạng Flutter Web và lưu trữ trên máy chủ hoặc CDN, cho phép cập nhật mà không cần phát hành lại SuperApp. Hệ thống phải có cơ chế bảo mật để ngăn chặn việc truy cập trái phép và đảm bảo SubApp chỉ chạy đúng trong môi trường được phép.
|
||||
|
||||
2. Thành phần kiến trúc
|
||||
|
||||
2.1 SuperApp (Flutter Native)
|
||||
- Chứa giao diện chính, điều hướng và dịch vụ dùng chung.
|
||||
- Sau khi đăng nhập, gọi API Metadata để lấy danh sách SubApp khả dụng.
|
||||
- Hiển thị menu động dựa trên dữ liệu trả về từ server.
|
||||
- Khi người dùng chọn SubApp, mở WebView:
|
||||
+ Nạp URL SubApp từ metadata.
|
||||
+ Truyền token JWT ngắn hạn và các cấu hình qua query param hoặc inject vào WebView bằng JavascriptChannel.
|
||||
- Thiết lập kênh liên lạc hai chiều giữa Native và SubApp.
|
||||
|
||||
2.2 Metadata API (Backend)
|
||||
- Xác thực người dùng gửi từ SuperApp.
|
||||
- Trả về danh sách SubApp khả dụng gồm:
|
||||
+ id
|
||||
+ displayName
|
||||
+ iconUrl
|
||||
+ launchUrl
|
||||
+ signedToken (JWT ngắn hạn với thông tin userId, hostAppId, subAppId, exp)
|
||||
- API bảo mật bằng HTTPS và yêu cầu header Authorization từ SuperApp.
|
||||
|
||||
2.3 SubApp (Flutter Web hoặc Web Bundle)
|
||||
- Phát triển và triển khai độc lập từ repository riêng, build dạng Flutter Web.
|
||||
- Đọc token và cấu hình từ biến window.__SUPERAPP_CONTEXT__ hoặc query param.
|
||||
- Gọi API backend với Authorization: Bearer token từ SuperApp.
|
||||
- Gửi sự kiện hoặc dữ liệu về Native qua JS Bridge.
|
||||
|
||||
2.4 Backend SubApp API
|
||||
- Xác thực token JWT cho mọi request.
|
||||
- Kiểm tra các claim: userId, hostAppId, subAppId, exp.
|
||||
- Từ chối truy cập nếu token không hợp lệ hoặc hết hạn.
|
||||
- Áp dụng CORS, giới hạn origin và/hoặc user-agent.
|
||||
|
||||
3. Quy trình hoạt động
|
||||
1. Người dùng đăng nhập vào SuperApp.
|
||||
2. SuperApp gọi Metadata API nhận danh sách SubApp và token launch.
|
||||
3. Người dùng chọn SubApp từ menu.
|
||||
4. SuperApp khởi tạo WebView với URL = launchUrl + token ngắn hạn, đồng thời inject biến JS chứa context (token, hostAppId, theme).
|
||||
5. SubApp đọc token và gọi API backend lấy dữ liệu.
|
||||
6. Backend xác thực token, trả dữ liệu nếu hợp lệ.
|
||||
7. Trạng thái và sự kiện trao đổi hai chiều qua JS Bridge giữa Native và SubApp.
|
||||
|
||||
4. Cơ chế bảo mật
|
||||
|
||||
4.1 JWT ngắn hạn
|
||||
- Mỗi lần mở SubApp, backend tạo token JWT mới với thời hạn ngắn, ví dụ 5 phút.
|
||||
- Token chứa các claim: userId, hostAppId, subAppId, exp.
|
||||
|
||||
4.2 Xác thực Backend
|
||||
- Bắt buộc mọi API gọi từ SubApp phải có token hợp lệ.
|
||||
- Backend kiểm tra chữ ký và claim.
|
||||
- Reject request nếu token hết hạn hoặc sai hostAppId.
|
||||
|
||||
4.3 Hạn chế nguồn truy cập
|
||||
- CORS chỉ cho phép origin từ domain CDN của SubApp.
|
||||
- Kiểm tra user-agent để xác nhận request xuất phát từ WebView SuperApp.
|
||||
|
||||
4.4 Giao tiếp an toàn
|
||||
- Luôn dùng HTTPS.
|
||||
- Không nhúng dữ liệu nhạy cảm vào mã nguồn SubApp.
|
||||
- Chỉ truyền những thông tin cần thiết vào JS Bridge.
|
||||
|
||||
5. Lợi ích
|
||||
- Cập nhật SubApp nhanh, không cần phát hành lại SuperApp.
|
||||
- Các nhóm phát triển SubApp làm việc độc lập.
|
||||
- Bảo mật kiểm soát qua token động và xác thực server.
|
||||
- Linh hoạt, dễ thêm/bớt SubApp qua metadata mà không thay đổi code SuperApp.
|
||||
|
||||
6. Sơ đồ kiến trúc mô tả dạng chữ
|
||||
[Người dùng]
|
||||
↓ Đăng nhập
|
||||
[SuperApp Flutter]
|
||||
↓ Fetch Metadata API (HTTPS + Auth)
|
||||
[Metadata API Backend] → Danh sách SubApp + JWT ngắn hạn
|
||||
↓
|
||||
Hiển thị menu SubApp
|
||||
↓ Người dùng chọn SubApp
|
||||
[WebView] ↔ JS Bridge ↔ [SubApp Flutter Web]
|
||||
↓
|
||||
Gọi API Backend (Bearer JWT)
|
||||
[SubApp Backend API] ← Xác thực JWT → Trả dữ liệu
|
||||
|
||||
7. Ví dụ code
|
||||
|
||||
Ví dụ Metadata API trả JSON:
|
||||
[
|
||||
{
|
||||
"id": "chat",
|
||||
"displayName": "Chat",
|
||||
"iconUrl": "https://cdn.domain.com/icons/chat.png",
|
||||
"launchUrl": "https://cdn.domain.com/chat/index.html",
|
||||
"signedToken": "JWT_STRING"
|
||||
},
|
||||
{
|
||||
"id": "payments",
|
||||
"displayName": "Payments",
|
||||
"iconUrl": "https://cdn.domain.com/icons/payments.png",
|
||||
"launchUrl": "https://cdn.domain.com/payments/index.html",
|
||||
"signedToken": "JWT_STRING"
|
||||
}
|
||||
]
|
||||
|
||||
Ví dụ trong SuperApp Flutter tạo WebView:
|
||||
WebViewController controller = WebViewController()
|
||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||
..addJavaScriptChannel('NativeBridge', onMessageReceived: (msg) {
|
||||
print("Nhận từ SubApp: ${msg.message}");
|
||||
})
|
||||
..setNavigationDelegate(NavigationDelegate(onPageFinished: (url) {
|
||||
controller.runJavaScript("""
|
||||
window.__SUPERAPP_CONTEXT__ = {
|
||||
token: "${signedToken}",
|
||||
hostAppId: "superapp-ios-android",
|
||||
theme: "light"
|
||||
};
|
||||
if(window.onSuperAppContext) window.onSuperAppContext(window.__SUPERAPP_CONTEXT__);
|
||||
""");
|
||||
}))
|
||||
..loadRequest(Uri.parse("${launchUrl}?token=${signedToken}&hostAppId=superapp-ios-android"));
|
||||
|
||||
Ví dụ trong SubApp (JS/Flutter Web):
|
||||
let token = (window.__SUPERAPP_CONTEXT__ && window.__SUPERAPP_CONTEXT__.token)
|
||||
|| new URL(window.location.href).searchParams.get('token');
|
||||
|
||||
fetch('https://api.domain.com/chat/messages', {
|
||||
headers: { 'Authorization': 'Bearer ' + token }
|
||||
}).then(r => r.json()).then(data => {
|
||||
console.log("Chat messages:", data);
|
||||
});
|
||||
|
||||
window.NativeBridge.sendMessage(JSON.stringify({action: 'miniappLoaded'}));
|
||||
4
reference.txt
Normal file
4
reference.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
https://developer.apple.com/app-store/review/guidelines/#third-party-software - Apple's regulations on mini apps and sub apps
|
||||
https://miniapp.zaloplatforms.com/community/1472418623687562947/nhung-app-flutter-vao-miniapp - Zalo's guide on how to embed mini apps (for reference only)
|
||||
https://www.facebook.com/groups/fluttervn/posts/1666571620545936/ - Flutter sub app discussion topic on Facebook
|
||||
https://medium.com/@vishalkusinha7301/micro-apps-in-flutter-a-scalable-architecture-for-super-apps-and-modular-teams-822e30b2557d - Micro-Apps in Flutter
|
||||
Reference in New Issue
Block a user