iOS类原生PWA的CAS认证流程异常:跳转Safari并重复打开页面
iOS Swift WebView封装PWA的CAS SSO认证窗口跳转问题
问题详情
我开发的Web应用基于外部CAS服务器实现SSO,认证流程为:
- 访问
myapp.com - 跳转至
whereareyoufrom.com/form - 跳转至
iamfromhere.com/login完成登录 - 最终返回
myapp.com
Android端通过PWABuilder封装的PWA完全正常,但iOS端用Swift WebView原生封装时出现异常:
- 能正常进入CAS登录页,但提交表单后会唤起Safari打开新窗口,且重复显示登录页
- 再次提交登录信息后,会跳转到
iamfromhere.com/home,而非应用内的myapp.com/home - 关闭Safari后,回到应用内的登录页
已尝试无效方案
- 在
WebView.swift中设置config.limitsNavigationsToAppBoundDomains = false - 在
index.html中添加<meta name="apple-mobile-web-app-capable" content="yes"> - 将所有外部域名添加到PWA的允许URL列表
当前状态(编辑补充)
把iamfromhere.com加入Settings.swift的authOrigins和Info.plist的WKAppBoundDomains后,认证流程可以正常走完,但仍会在Safari打开重复窗口。
解决思路
1. 拦截新窗口请求,在应用内WebView加载
实现WKUIDelegate的webView(_:createWebViewWith:for:windowFeatures:)方法,拦截WebView的新窗口创建请求,直接在当前WebView内加载目标URL,避免唤起Safari:
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? { // 拦截target="_blank"的跳转请求 guard let url = navigationAction.request.url, navigationAction.targetFrame == nil else { return nil } webView.load(URLRequest(url: url)) return nil }
注意要给WebView设置uiDelegate = self。
2. 移除CAS页面的target="_blank"属性
检查CAS登录表单或跳转链接是否带有target="_blank",如果有,直接修改为target="_self";如果无法修改CAS页面代码,可在WebView加载时注入JS移除该属性:
document.addEventListener('DOMContentLoaded', () => { // 处理所有表单 document.querySelectorAll('form').forEach(form => form.target = '_self'); // 处理所有新窗口链接 document.querySelectorAll('a[target="_blank"]').forEach(link => link.target = '_self'); });
通过WKUserScript将这段JS注入WebView:
let script = WKUserScript(source: jsCode, injectionTime: .atDocumentEnd, forMainFrameOnly: true) config.userContentController.addUserScript(script)
3. 完善WKAppBoundDomains配置
确保Info.plist中的WKAppBoundDomains包含所有跳转涉及的域名,格式为数组,每个域名不带协议头:
<key>WKAppBoundDomains</key> <array> <string>myapp.com</string> <string>whereareyoufrom.com</string> <string>iamfromhere.com</string> </array>
4. 检查WebView的导航代理逻辑
确认WKNavigationDelegate的webView(_:decidePolicyFor:decisionHandler:)方法中,没有错误地允许外部浏览器打开链接:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { // 确保所有跳转都在应用内WebView处理 decisionHandler(.allow) }
内容的提问来源于stack exchange,提问作者agatherc
相关产品推荐
相关产品推荐

