webview_flutter结合appTrackingTransparency处理Cookie技术咨询(含苹果拒审解决及示例代码需求)
Hey fellow dev, I’ve been through this exact scenario where an app got rejected because WebView cookies triggered Apple’s tracking rules. Here’s a practical implementation to handle ATT authorization alongside cookie control, plus tips to "hide" (restrict) unwanted cookies.
1. Core Logic Overview
- Trigger ATT Prompt: Detect when the WebView attempts to set cookies, then launch the App Tracking Transparency authorization dialog.
- Cookie Control:
- If user grants authorization: Allow cookies to be stored and used normally.
- If user denies/restricts: Block cookie storage and clear any existing related cookies.
2. Step-by-Step Implementation Code
First, add required dependencies to your pubspec.yaml:
dependencies: webview_flutter: ^4.4.0 # Use latest stable version app_tracking_transparency: ^2.0.4 # Use latest stable version
2.1 Initialize ATT & Cookie Manager
import 'package:app_tracking_transparency/app_tracking_transparency.dart'; import 'package:webview_flutter/webview_flutter.dart'; import 'package:webview_flutter_android/webview_flutter_android.dart'; import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart'; class WebViewCookieHandler extends StatefulWidget { final String initialUrl; const WebViewCookieHandler({super.key, required this.initialUrl}); @override State<WebViewCookieHandler> createState() => _WebViewCookieHandlerState(); } class _WebViewCookieHandlerState extends State<WebViewCookieHandler> { late WebViewController _controller; final CookieManager _cookieManager = CookieManager(); bool _attAuthorized = false; @override void initState() { super.initState(); _initAtt(); _initWebViewController(); } // Initialize ATT status on app start Future<void> _initAtt() async { final TrackingStatus status = await AppTrackingTransparency.requestTrackingAuthorization(); setState(() { _attAuthorized = status == TrackingStatus.authorized; }); } // Setup WebView controller with cookie intercept logic void _initWebViewController() { late final PlatformWebViewControllerCreationParams params; if (WebViewPlatform.instance is WebKitWebViewPlatform) { params = WebKitWebViewControllerCreationParams( allowsInlineMediaPlayback: true, mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{}, ); } else { params = const PlatformWebViewControllerCreationParams(); } final WebViewController controller = WebViewController.fromPlatformCreationParams(params); // Listen for page start to check/trigger ATT before cookies are set controller.setNavigationDelegate(NavigationDelegate( onPageStarted: (String url) async { if (!_attAuthorized) { // Re-request ATT if user hasn't decided yet final TrackingStatus status = await AppTrackingTransparency.requestTrackingAuthorization(); setState(() { _attAuthorized = status == TrackingStatus.authorized; }); // Update cookie permissions right after ATT decision await _updateCookiePermissions(); } }, onNavigationRequest: (NavigationRequest request) async { // Block cookie headers if user denied ATT if (!_attAuthorized) { final modifiedHeaders = Map.from(request.headers)..remove('Cookie'); // Note: For full blocking, you might need to use a custom request interceptor return NavigationDecision.navigate; } return NavigationDecision.navigate; }, )); // Load initial URL with base settings controller.loadRequest(Uri.parse(widget.initialUrl)); _controller = controller; } // Update cookie permissions based on ATT status Future<void> _updateCookiePermissions() async { if (!_attAuthorized) { // Clear all existing cookies for the WebView await _cookieManager.deleteAllCookies(); // Restrict cookies on iOS (WKWebView) if (WebViewPlatform.instance is WebKitWebViewPlatform) { final WebKitWebViewController webKitController = _controller.platform as WebKitWebViewController; await webKitController.setPreferences( WebKitPreferences( allowsContentJavaScript: true, thirdPartyCookiesEnabled: false, ), ); } // Disable cookie acceptance on Android if (WebViewPlatform.instance is AndroidWebViewPlatform) { final AndroidWebViewController androidController = _controller.platform as AndroidWebViewController; await androidController.setSettings(AndroidSettings( javaScriptEnabled: true, acceptCookie: false, )); } } else { // Re-enable cookies if user authorized if (WebViewPlatform.instance is AndroidWebViewPlatform) { final AndroidWebViewController androidController = _controller.platform as AndroidWebViewController; await androidController.setSettings(AndroidSettings(acceptCookie: true)); } if (WebViewPlatform.instance is WebKitWebViewPlatform) { final WebKitWebViewController webKitController = _controller.platform as WebKitWebViewController; await webKitController.setPreferences(WebKitPreferences(thirdPartyCookiesEnabled: true)); } } } @override Widget build(BuildContext context) { return WebViewWidget(controller: _controller); } }
3. How to "Hide" Cookies in WebView Flutter
"Hiding" cookies typically means restricting tracking-focused cookies to avoid Apple’s rejection triggers. Here are actionable methods:
- Block Third-Party Cookies: On iOS, disable
thirdPartyCookiesEnabledin WKWebView preferences. On Android 11+, useacceptThirdPartyCookiesto block cross-domain cookies. - Auto-Clear Cookies: Delete cookies when the WebView is disposed or when ATT is denied, using
_cookieManager.deleteCookiesForDomain()to target specific domains instead of all. - Request Interception: Use
NavigationDelegate.onNavigationRequestto strip Cookie headers from outgoing requests if the user hasn’t authorized tracking. - Restrict Cookie Scope: Manually set cookies only for your first-party domain using
CookieManager.setCookie()with strict domain and path parameters.
4. Additional Compliance Tips
- Update Info.plist: Add the mandatory
NSUserTrackingUsageDescriptionto explain why you need tracking authorization:<key>NSUserTrackingUsageDescription</key> <string>We use tracking to personalize your in-app web experience and improve our services.</string> - Test Edge Cases: Verify that the ATT prompt appears before any cookies are stored, and that denied authorization fully blocks cookie persistence.
内容的提问来源于stack exchange,提问作者yusuf
相关产品推荐
相关产品推荐

