Flutter InAppWebView Google登录失败
前段时间用户反馈应用内部网页使用X(原Twitter)的时候Google登录按钮一直在Loading,部分用户没有Google登录选项,极少数用户出现了Google登录按钮,但是点击跳转之后白屏。经多方查找资料,问题解决,这里记录一下处理过程。
声明:以下均在iOS设备上调试,Android上表现不太一致,但产生的原因和解决方式一样
环境
Flutter:3.22.2
flutter_inappwebview:6.0.0
运行设备:iOS 17.5.1
现象
如果下图所示,Google登录按钮一直在Loading,
有少部分用户加载出登录按钮,但是跳转之后白屏。
排查过程
因为使用的flutter_inappwebview,第一反应到它Github仓库的issues搜索了一下关键词google sign in。看了所有的搜索结果没想到还真有发现,都指向了这里,虽然表现出来的现象都不太一样:
Authorisation Error,Error 403:disallowed_useragent
Access blocked: This app's request is invalid
似乎都与userAgent有关,评论里很多人都回复设置了一个userAgent后,Google登录恢复正常,但也有人很表示该方法无效。
我也尝试了一下,随便网上找了一个userAgent,设置发现😂:
看来X有检测UserAgent,找的太旧了换一个新的
Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/119.0.6045.169 Mobile/15E148 Safari/604.1
正当我以为事情这么简单的时候,点击Google登录然后打开一页白屏!
这时候我注意到控制台打印:
[IOSInAppWebViewController] (iOS) WebView ID 0 calling "onTitleChanged" using {title: X。尽是新鲜事 / X}
[IOSInAppWebViewController] (iOS) WebView ID 0 calling "onWindowFocus" using []
[IOSInAppWebViewController] (iOS) WebView ID 0 calling "onWindowFocus" using []
[IOSInAppWebViewController] (iOS) WebView ID 0 calling "onCreateWindow" using {isForMainFrame: false, targetFrame: null, navigationType: -1, shouldPerformDownload: false, windowId: 4, hasGesture: null, windowFeatures: {width: 350.0, height: 550.0, y: 147.0, statusBarVisibility: false, toolbarsVisibility: false, allowsResizing: false, menuBarVisibility: false, x: 20.0}, request: {headers: {Referer: https://x.com/}, allowsCellularAccess: true, httpShouldUsePipelining: false, networkServiceType: 0, body: null, timeoutInterval: 2147483647.0, attribution: 0, method: GET, allowsConstrainedNetworkAccess: true, allowsExpensiveNetworkAccess: true, mainDocumentURL: null, url: https://accounts.google.com/gsi/select?client_id=49625052041-kgt0hghf445lmcmhijv46b715m2mpbct.apps.googleusercontent.com&ux_mode=popup&ui_mode=bottom_sheet&as=DiJIrUBftb5akVzSPBW8Kw&channel_id=9b9a69a2a67be16b5a1a42ac0bd12249f44b307330d80f07e39e1eba1909d5a8&origin=https%3A%2F%2Fx.com, cachePolicy: 0, httpShouldHandleCookies: true, assumesHTTP3Capable:...
[IOSInAppWebViewController] (iOS) WebView ID 0 calling "onProgressChanged" using {progress: 10}
[IOSInAppWebViewController] (iOS) WebView ID 0 calling "onUpdateVisitedHistory" using {isReload: null, url: https://accounts.google.com/gsi/select?client_id=49625052041-kgt0hghf445lmcmhijv46b715m2mpbct.apps.googleusercontent.com&ux_mode=popup&ui_mode=bottom_sheet&as=DiJIrUBftb5akVzSPBW8Kw&channel_id=9b9a69a2a67be16b5a1a42ac0bd12249f44b307330d80f07e39e1eba1909d5a8&origin=https%3A%2F%2Fx.com}
[IOSInAppWebViewController] (iOS) WebView ID 0 calling "onLoadStart" using {url: https://accounts.google.com/gsi/select?client_id=49625052041-kgt0hghf445lmcmhijv46b715m2mpbct.apps.googleusercontent.com&ux_mode=popup&ui_mode=bottom_sheet&as=DiJIrUBftb5akVzSPBW8Kw&channel_id=9b9a69a2a67be16b5a1a42ac0bd12249f44b307330d80f07e39e1eba1909d5a8&origin=https%3A%2F%2Fx.com}
[IOSInAppWebViewController] (iOS) WebView ID 0 calling "onProgressChanged" using {progress: 100}
[IOSInAppWebViewController] (iOS) WebView ID 0 calling "onProgressChanged" using {progress: 10}
[IOSInAppWebViewController] (iOS) WebView ID 0 calling "onProgressChanged" using {progress: 30}
[IOSInAppWebViewController] (iOS) WebView ID 0 calling "onTitleChanged" using {title: }
[IOSInAppWebViewController] (iOS) WebView ID 0 calling "onPageCommitVisible" using {url: https://accounts.google.com/gsi/select?client_id=49625052041-kgt0hghf445lmcmhijv46b715m2mpbct.apps.googleusercontent.com&ux_mode=popup&ui_mode=bottom_sheet&as=DiJIrUBftb5akVzSPBW8Kw&channel_id=9b9a69a2a67be16b5a1a42ac0bd12249f44b307330d80f07e39e1eba1909d5a8&origin=https%3A%2F%2Fx.com}
[IOSInAppWebViewController] (iOS) WebView ID 0 calling "onTitleChanged" using {title: Sign In - Google Accounts}
[IOSInAppWebViewController] (iOS) WebView ID 0 calling "onProgressChanged" using {progress: 100}
注意看第4行onCreateWindow
,联想到平时在PC上Google 登录确实有新开一个窗口,于是做以下尝试:
onCreateWindow: (controller,action) async {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: SizedBox(
width: MediaQuery.of(context).size.width,
height: 400,
child: InAppWebView(
// 这里设置windowId非常重要
windowId: action.windowId,
initialSettings: InAppWebViewSettings(
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/119.0.6045.169 Mobile/15E148 Safari/604.1',
),
),
),
);
},
);
return true;
}
实现了InAppWebView的onCreateWindow
⚠️注意,这里Dialog里的InAppWebView也必须设置userAgent
再次尝试竟然好了
成功登录Twitter,至此问题解决。
总结
解决这个问题有两步:
设置UserAgent
如上文所示,实现
onCreateWindow
方法,注意设置windowId和Dialog里InAppWebView的userAgent
UserAgent闲聊
我一直认为InAppWebView有默认的userAgent,看代码发现默认的是空字符串。但是无论是页面加载成功后用JS方法获取,还是拦截网络请求,都能看到有正确的userAgent,自己手动设置后,均变为设置后的值。没有深入研究这个问题,猜测可能是:对应iOS或Android的原生WebView有默认值,Flutter侧只是提供了一个修改手段。
写死一个userAgent虽然不影响功能,但可能产生一些未知的问题,建议需要手动设置的时候还是根据规则生成。
查资料的时候还发现一个很有趣的问题,你猜为什么不同平台不同浏览器的UserAgent都以Mozilla开头?
- 1
- 0
-
赞助
微信支付宝 -
分享