如何在 UIWebView 中显示身份验证质询?
Posted
技术标签:
【中文标题】如何在 UIWebView 中显示身份验证质询?【英文标题】:How to display the Authentication Challenge in UIWebView? 【发布时间】:2010-12-18 16:47:17 【问题描述】:我正在尝试通过 UIWebView 访问安全网站。当我通过 safari 访问它时,我收到了身份验证挑战,但同样的问题没有出现在应用程序的 UIWebView 中。我怎样才能让它出现?
任何指针、示例代码或链接都会非常有帮助。非常感谢。
【问题讨论】:
【参考方案1】:这实际上非常简单...我相信您可以在显示身份验证挑战委托时显示 UIAlertView(或在加载 URL 之前,如果您确定您正在点击的 URL 会提示验证登录信息)。无论如何,诀窍是创建自己的NSURLConnection
,然后我会做一些逻辑来保存是否使用了授权委托。
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
NSLog(@"Did start loading: %@ auth:%d", [[request URL] absoluteString], _authed);
if (!_authed)
_authed = NO;
/* pretty sure i'm leaking here, leave me alone... i just happen to leak sometimes */
[[NSURLConnection alloc] initWithRequest:request delegate:self];
return NO;
return YES;
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
NSLog(@"got auth challange");
if ([challenge previousFailureCount] == 0)
_authed = YES;
/* SET YOUR credentials, i'm just hard coding them in, tweak as necessary */
[[challenge sender] useCredential:[NSURLCredential credentialWithUser:@"username" password:@"password" persistence:NSURLCredentialPersistencePermanent] forAuthenticationChallenge:challenge];
else
[[challenge sender] cancelAuthenticationChallenge:challenge];
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
NSLog(@"received response via nsurlconnection");
/** THIS IS WHERE YOU SET MAKE THE NEW REQUEST TO UIWebView, which will use the new saved auth info **/
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:]];
[_webView loadRequest:urlRequest];
- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection;
return NO;
【讨论】:
不适用于 POST。即使对此进行简单的修改仍然不适用于 POST。 这不适用于任何未经身份验证的请求(_authed 始终 == NO 并触发无限循环)。即使你解决了这个问题,这仍然不起作用,因为 shouldStartLoadWithRequest 会在每个网页上多次触发,最终导致网页视图加载的最后一个 url 请求是网页视图中显示的唯一内容。 将“_authed = YES”添加到 didReceiveResponse。当服务器由于某种原因没有发送质询请求时,这可以防止无限循环。 答案有几个问题,但它给出了解决已验证请求问题的基本概念。 好像在连接中断的时候,auth数据丢失了,而_authed
还是YES
,再也没有机会进行auth了。【参考方案2】:
您还可以在 url 中提供您的凭据。 只需在 'http://' 和 'page url' 之间添加用户名和密码。
NSString *urlString = @"http://username:password@domain.com/home";
[webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]]];
【讨论】:
同一网络上的某人可以清楚地看到请求。 => 使用带有 SSL 证书的 https 可以解决这个问题。您可以使用 Wireshark 等嗅探器进行检查。【参考方案3】:如您所知,UIWebView 不提供与服务器通信的机会。 我以这种方式解决了这个问题:在 UIWebView 的委托方法 shouldStartLoadWithRequest 中,我启动了与 NSURLConnection 的另一个连接,并且已经在委托 NSURLConnection 的方法中 didReceiveAuthenticationChallenge 处理了来自服务器的挑战。 Аnd 在方法 didReceiveResponse (如果挑战来了)然后再次在同一个 UIWebView 中加载相同的 URL(挑战已经被处理:)。不要忘记在 didReceiveResponse 中取消连接,否则会导致流量翻倍。
【讨论】:
如果已经收到响应,取消连接如何防止流量翻倍?【参考方案4】:如果您遇到 Zach 在 Sahil 的回答中描述的症状:
正如 y5h 所说,将 `_authed = YES' 添加到 didReceiveResponse 方法中,这将停止无限循环。即使身份验证不成功,您也需要将其视为已通过身份验证,因此如果不需要身份验证,它将尝试继续加载页面,如果确实需要身份验证,那么它将像往常一样失败。
对于 shouldStartLoadWithRequest: 多次触发的第二个症状(由于网页上嵌入的内容),它只会显示最后加载的内容而不是整个网页,请执行以下操作:
在 shouldStartLoadWithRequest: 方法中,将其添加到顶部
if(webview.loading) //if url requests come through while its loading, its probably embedded content
return YES;
编辑:如果页面完全加载,则上述方法会出现问题,然后加载更多嵌入内容,与 facebook 中断,这是迄今为止我看到的唯一情况
这将使网址在网站尝试加载时通过。我不确定是否可以安全地假设初始请求之后的每个 url 都是嵌入内容,但就我的目的而言,它似乎有效,所以也许它也适合你。
另外,使用
- (void) connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
因为
connection:canAuthenticateAgainstProtectionSpace:
connection:didReciveAuthenticationChallenge:
connection:didCancelAuthenticationChallenge:
已被贬低,对我来说,您无法使用它们对 https 网站进行身份验证
【讨论】:
【参考方案5】:我想使用以下 pod 提出另一个答案: https://github.com/jivesoftware/JiveAuthenticatingHTTPProtocol
它包含一个示例,展示了如何使用UIAlertView
向用户询问密码,并且可以很容易地适应例如从本地数据库返回已保存的密码。
免责声明:我与 Jive 没有任何关系,我也从未加入过,这只是一个工具的建议,它在为此苦苦挣扎了几天后帮助了我。
【讨论】:
以上是关于如何在 UIWebView 中显示身份验证质询?的主要内容,如果未能解决你的问题,请参考以下文章
在 ReactJS 中的 Spotify API 上为 PKCE 身份验证创建代码验证器和质询
在 AWS Cognito 中回答 NEW_PASSWORD_REQUIRED 质询后继续使用自定义身份验证流程