如何在WKWebView的Cookie中设置MSAL访问令牌以避免重复登录
1. 确保获取到正确的MSAL访问令牌
首先要确认请求的scopes包含SharePoint对应的权限,比如目标站点的AllSites.Read或者Sites.Read.All,同时加上offline_access用于后续静默刷新令牌。示例Swift代码:
let targetSharePointScope = "https://your-tenant.sharepoint.com/AllSites.Read" let scopes = [targetSharePointScope, "offline_access"] let interactiveParams = MSALInteractiveTokenParameters(scopes: scopes, presentationStyle: .automatic) yourMSALApplication.acquireToken(with: interactiveParams) { result, error in guard let authResult = result else { // 处理认证错误 return } // 保存令牌和账号信息 self.storedAccessToken = authResult.accessToken self.currentMSALAccount = authResult.account }
2. 加载页面时携带令牌请求头
不要直接用wkWebView.load(URL(string: "your-sharepoint-url")!),而是构造带Authorization头的URLRequest:
guard let spUrl = URL(string: "https://your-tenant.sharepoint.com/sites/your-target-site"), let token = storedAccessToken else { return } var spRequest = URLRequest(url: spUrl) spRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization") wkWebView.load(spRequest)
3. 拦截子请求并添加令牌(核心步骤)
SharePoint页面加载后会发起大量子请求(静态资源、API调用等),这些请求也需要携带令牌才能免登。通过WKNavigationDelegate拦截请求并修改请求头:
extension YourViewController: WKNavigationDelegate { func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { guard let requestUrl = navigationAction.request.url, requestUrl.host?.contains("sharepoint.com") == true, let token = storedAccessToken else { decisionHandler(.allow) return } // 避免重复添加Authorization头 if navigationAction.request.value(forHTTPHeaderField: "Authorization") == nil { var modifiedRequest = navigationAction.request modifiedRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization") webView.load(modifiedRequest) decisionHandler(.cancel) // 取消原请求,用带令牌的新请求替代 } else { decisionHandler(.allow) } } }
别忘了给wkWebView设置navigationDelegate = self。
4. 处理令牌过期问题
当令牌过期时,用MSAL静默刷新令牌,更新后重新加载页面:
func refreshAccessTokenIfNeeded() { guard let account = currentMSALAccount, let scope = targetSharePointScope else { return } let silentParams = MSALSilentTokenParameters(scopes: [scope], account: account) yourMSALApplication.acquireTokenSilent(with: silentParams) { result, error in if let refreshError = error as? MSALError { if refreshError.code == .interactionRequired { // 静默刷新失败,需要重新弹出登录界面 self.acquireInteractiveToken() } else { // 处理其他刷新错误 } return } guard let refreshedResult = result else { return } self.storedAccessToken = refreshedResult.accessToken // 刷新令牌后重新加载页面 self.wkWebView.reload() } }
注意事项
- 验证令牌的**受众(aud)**是否与你的SharePoint站点域名一致,可以通过jwt.io解析令牌查看。
- 确保MSAL认证的账号拥有目标SharePoint站点的访问权限,否则即使带令牌也会被拒绝。
- 测试时注意清理WKWebView的缓存,避免旧的登录会话干扰测试结果。
内容的提问来源于stack exchange,提问作者Vikas Rajput
相关产品推荐
相关产品推荐

