iOS应用实现SP发起的SAML SSO(Http-Post绑定)方案咨询
我来分享下iOS上实现SP发起、HTTP-POST绑定的SAML SSO的主流方案,以及两种浏览器方式的具体处理思路——这些都是业内成熟应用常用的做法:
主流方案选型建议
多数生产级iOS应用会优先选择**外部浏览器(系统Safari)**的方案,原因很简单:它能利用系统自带的身份凭证管理(比如iCloud钥匙串)、规避WebView潜在的XSS风险,而且完全符合Apple的审核规范(Apple明确推荐用系统浏览器处理第三方认证流程)。不过内部WebView也有适用场景,比如需要高度定制认证UI或者必须在应用内闭环完成认证时。
一、使用外部浏览器(系统Safari)的实现思路
核心问题是如何让IDP的POST断言回调回你的应用,这里最可靠的方式是用Universal Links(通用链接)(不推荐Custom URL Schemes,因为存在被劫持的安全风险),具体步骤如下:
- 配置Universal Links:
- 在Apple开发者后台开启你的应用的Associated Domains功能;
- 在你的SP服务域名根目录上传
apple-app-site-association配置文件,指定能唤起应用的路径(比如你的ACS回调路径); - 在Xcode的项目配置里添加对应的Associated Domains(格式为
applinks:your-sp-domain.com)。
- 发起SAML认证请求:
构造SP发起的AuthnRequest(HTTP-POST格式),生成一个包含该表单的HTML页面,调用UIApplication.shared.open(_:options:completionHandler:)打开这个页面(或者直接跳转到IDP的登录入口URL,带上SP的相关参数)。
- 发起SAML认证请求:
- 处理IDP回调:
当IDP完成用户认证后,会向你的SP的Assertion Consumer Service(ACS)URL发送POST请求,这个ACS URL必须是你配置好的Universal Link。当Safari加载这个链接时,系统会自动唤起你的应用。
- 在UIKit里,你可以通过
application(_:continue:restorationHandler:)方法获取回调的NSUserActivity,从中解析出Universal Link的参数; - 在SwiftUI里,用
onContinueUserActivity修饰符监听Universal Link的回调。
- 处理IDP回调:
- 提取SAML断言:
你的ACS页面需要做一个中转:接收到IDP的POST表单后,用JS提取出表单里的SAMLResponse参数(通常是base64编码的),然后跳转到带参数的Universal Link,比如:
// ACS页面的JS代码 document.addEventListener('DOMContentLoaded', function() { const samlResponse = document.querySelector('input[name="SAMLResponse"]').value; window.location.href = 'your-app-universal-link://saml/callback?response=' + encodeURIComponent(samlResponse); });应用拿到这个回调URL后,解析query参数里的
response即可获取SAML断言。- 提取SAML断言:
二、使用内部WebView的实现思路
如果必须用WebView(比如要定制登录页的UI风格),获取POST请求体的方法主要有两种,这里只推荐用WKWebView(UIWebView已被Apple废弃,安全性差):
方法1:拦截HTTP请求
利用WKNavigationDelegate的拦截能力,捕获WebView向ACS URL发起的POST请求,直接从请求体中提取断言:
- 实现
webView(_:decidePolicyFor:decisionHandler:)方法,判断请求的URL是否为你的ACS地址; - 如果是POST请求,取出
request.httpBody,将其转换为字符串后解析application/x-www-form-urlencoded格式的表单数据,提取SAMLResponse参数。
示例代码片段:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { guard let url = navigationAction.request.url, url.absoluteString.contains("your-acs-url") else { decisionHandler(.allow) return } if let httpBody = navigationAction.request.httpBody, let bodyString = String(data: httpBody, encoding: .utf8) { // 解析表单数据 let params = bodyString.components(separatedBy: "&").reduce(into: [String: String]()) { dict, pair in let parts = pair.components(separatedBy: "=") if parts.count == 2, let key = parts[0].removingPercentEncoding, let value = parts[1].removingPercentEncoding { dict[key] = value } } if let samlResponse = params["SAMLResponse"] { // 拿到断言,后续处理 print("SAML Response: \(samlResponse)") } } decisionHandler(.allow) }
方法2:注入JS脚本提取断言
通过向WebView注入JS脚本,监听表单提交事件或者直接提取页面中的SAMLResponse值,再通过WKScriptMessageHandler传递给原生代码:
- 先配置WebView的
configuration.userContentController,添加一个消息处理器; - 在WebView加载ACS页面后,注入JS脚本监听表单提交;
- 原生实现
WKScriptMessageHandler的方法接收传递过来的断言。
示例代码:
// 配置WebView let configuration = WKWebViewConfiguration() configuration.userContentController.add(self, name: "samlCallback") let webView = WKWebView(frame: view.bounds, configuration: configuration) // 注入JS脚本 let jsScript = """ document.addEventListener('submit', function(e) { e.preventDefault(); let samlResponse = document.querySelector('input[name="SAMLResponse"]').value; window.webkit.messageHandlers.samlCallback.postMessage(samlResponse); }); """ let userScript = WKUserScript(source: jsScript, injectionTime: .atDocumentEnd, forMainFrameOnly: true) configuration.userContentController.addUserScript(userScript) // 实现WKScriptMessageHandler协议 func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { if message.name == "samlCallback", let samlResponse = message.body as? String { // 拿到断言 print("SAML Response: \(samlResponse)") } }
三、最终选型总结
- 优先选择外部浏览器+Universal Links:这是大厂应用的标准做法,既安全又符合Apple生态的用户体验,还能避免WebView的诸多安全隐患;
- 内部WebView仅在特殊场景下使用:比如必须定制认证UI,或者业务要求认证流程完全在应用内完成,此时一定要做好安全防护(比如限制WebView的JS权限、验证请求来源等)。
内容的提问来源于stack exchange,提问作者Bablu Joshi
相关产品推荐
相关产品推荐

