Flutter WebView添加Bearer授权请求头失败问题求助
我帮你捋一捋这个问题哈——你遇到的其实是WebView的一个常见坑:初始loadUrl传入的请求头只会对第一个请求生效,后续页面跳转、资源加载或者JS发起的请求都不会自动带上这个Authorization头,不管你用webview_flutter、flutter_webview_pro还是其他包,这个逻辑基本都是一致的。
核心解决方案:拦截所有请求,统一添加Authorization头
最可靠的做法是拦截WebView的所有导航请求,手动给每个请求带上Bearer令牌后再加载。下面以官方的webview_flutter包为例,给你修改代码:
import 'package:flutter/material.dart'; import 'package:skin_technology/core/consts/app_colors.dart'; import 'package:skin_technology/core/session_data/repo/session_data_service.dart'; import 'package:webview_flutter/webview_flutter.dart'; class CatalogWebView extends StatefulWidget { const CatalogWebView({Key? key}) : super(key: key); @override State<CatalogWebView> createState() => _CatalogWebViewState(); } class _CatalogWebViewState extends State<CatalogWebView> { late WebViewController _webController; String? _authToken; @override void initState() { super.initState(); // 提前获取令牌并保存到state中 _fetchAuthToken(); } Future<void> _fetchAuthToken() async { final sessionData = await SessionDataService.sessionData; setState(() { _authToken = sessionData?.token; }); } // 封装带Authorization头的URL加载方法 Future<void> _loadUrlWithAuth(String url) async { if (_authToken == null) return; final headers = {"Authorization": "Bearer $_authToken"}; await _webController.loadRequest( WebRequest( uri: Uri.parse(url), headers: headers, ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('КАТАЛОГ'), backgroundColor: AppColors.darkMainColor, ), body: _authToken == null ? const Center(child: CircularProgressIndicator()) : WebView( javascriptMode: JavascriptMode.unrestricted, initialUrl: 'about:blank', // 先加载空白页,避免初始请求漏带头 onWebViewCreated: (controller) async { _webController = controller; // 第一次加载目标页面 await _loadUrlWithAuth('https://clubskt.ru/client/catalog'); }, navigationDelegate: (NavigationRequest request) { // 拦截所有导航请求,手动添加令牌后加载 _loadUrlWithAuth(request.url); return NavigationDecision.prevent; // 阻止默认的无请求头加载 }, ), ); } }
为什么这个方案有效?
- 提前在
initState中获取令牌并保存,避免在UI构建中重复异步请求 - 用
navigationDelegate拦截所有页面跳转、新URL加载请求,确保每个请求都带上Authorization头 - 封装
_loadUrlWithAuth方法,避免重复写请求头逻辑 - 初始加载空白页,确保第一次请求就带正确的令牌
备选方案:JavaScript注入(仅适用于AJAX请求)
如果你的页面主要是通过JS发起AJAX请求,也可以尝试注入JS来给所有XMLHttpRequest添加请求头,但这个方法无法覆盖页面跳转类的请求,所以只作为备选:
// 在WebView的onPageFinished回调中添加 onPageFinished: (url) { if (_authToken == null) return; _webController.runJavascript(''' (function() { // 覆盖XMLHttpRequest的open方法,自动添加Authorization头 const originalOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url) { this.setRequestHeader('Authorization', 'Bearer $_authToken'); return originalOpen.apply(this, arguments); }; // 如果页面用fetch API,也需要覆盖 const originalFetch = window.fetch; window.fetch = function(resource, options = {}) { options.headers = { ...options.headers, 'Authorization': 'Bearer $_authToken' }; return originalFetch(resource, options); }; })(); '''); }
额外注意事项
- 确保服务器端允许跨域请求携带Authorization头(如果WebView加载的页面域名和API域名不同)
- 测试时可以清除WebView缓存,避免旧的无请求头请求被缓存
- 如果使用其他WebView包(如flutter_webview_pro),核心思路一致:找到请求拦截的回调,手动添加请求头后重新加载
内容的提问来源于stack exchange,提问作者Angelina Gromova
相关产品推荐
相关产品推荐

