Same-Origin Policy (SOP) hạn chế script từ origin A truy cập tài nguyên origin B. Trên mobile app (hybrid/native), quy tắc áp dụng khác so với web browser.
1. Hybrid App (Cordova/PhoneGap/Capacitor/Ionic)
- App chạy trong WebView (system webview).
- Mặc định: WebView tuân theo SOP như browser thông thường.
- Giải pháp: Cấu hình allow-navigation và allow-intent trong
config.xml, hoặc dùngcordova-plugin-whitelist.
<!-- config.xml (Cordova) --> <access origin="*" /> <!-- Cho phép tất cả domain (dev) --> <!-- Hoặc cụ thể --> <access origin="https://api.example.com" /> <access origin="https://*.example.com" subdomains="true" /> <allow-navigation href="https://example.com/*" /> <allow-intent href="https://*/*" /> <allow-intent href="https://*/*" />
Capacitor (Ionic): Cập nhật capacitor.config.json:
{
"server": {
"allowNavigation": ["api.example.com", "*.example.com"],
"cleartext": true // Cho phép HTTP (chỉ dev)
}
}
2. Native App (Android/iOS) - Không có SOP cho file://
- Native app load file local:
file:///android_asset/www/index.html(Android) hoặcfile:///var/mobile/.../index.html(iOS). - file:// origin được coi là "opaque origin" - không áp dụng SOP chuẩn.
- Có thể fetch/XHR đến bất kỳ domain nào mà không bị chặn bởi CORS/SOP (vì không có origin để so sánh).
Android (WebView)
WebView webView = findViewById(R.id.webview);
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setAllowFileAccess(true);
settings.setAllowContentAccess(true);
settings.setAllowFileAccessFromFileURLs(true); // Quan trọng: cho phép file:// truy cập file:// khác
settings.setAllowUniversalAccessFromFileURLs(true); // Cho phép file:// truy cập network
webView.loadUrl("file:///android_asset/www/index.html");
iOS (WKWebView)
let webView = WKWebView(frame: view.bounds) webView.configuration.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs") webView.loadFileURL(Bundle.main.url(forResource: "index", withExtension: "html")!, allowingReadAccessTo: Bundle.main.resourceURL!)
3. Bảo mật: Không lạm dụng "allow all"
| Cách | Rủi ro | Khuyến nghị |
|---|---|---|
access origin="*" | Mọi domain đều truy cập được app data | Chỉ dev, không production |
setAllowUniversalAccessFromFileURLs(true) | file:// có thể đọc file local khác, gọi API bất kỳ | Chỉ khi cần thiết, validate input |
| Domain cụ thể | An toàn | ✅ Production |
| Backend proxy | App chỉ gọi API của mình, server gọi API bên thứ 3 | ✅ Best practice |
4. CORS trên Mobile WebView
- Nếu app load
https://app.example.com(online), SOP/CORS áp dụng bình thường như browser. - Server API phải trả header
Access-Control-Allow-Origin: https://app.example.com(hoặc *). - Cookie/Credential: Cần
Access-Control-Allow-Credentials: truevà client setcredentials: 'include'.
Tóm tắt
- Hybrid (Cordova/Capacitor): Cấu hình whitelist domain trong config.xml/capacitor.config.json.
- Native WebView (file://): Không có SOP, truy cập tự do network/file local (cần bật settings cho phép).
- Production: Chỉ whitelist domain cần thiết, dùng backend proxy cho API bên thứ 3.