我们的应用程序使用NSURLSession
来使用RESTful服务调用。呼叫本身通过反向代理进行路由,以辅助后端的会话管理,安全性等。我们遇到的唯一问题与身份验证有关。当用户尝试通过浏览器或REST调用访问受保护资源并且未经过身份验证时,反向代理会显示HTML登录页面。
问题是,我们希望利用NSURLSession
自动处理身份验证质询的能力。但是,NSURLSession
无法识别我们正在返回身份验证质询,因为没有HTTP 401或其他错误代码返回给客户端。反向代理发回200,因为HTML已成功传递。我们能够通过检查客户端中的HTML来识别它是登录页面,但我们希望能够使用自定义NSURLAuthenticationChallenge
来处理身份验证(如果可能的话),以便{{验证成功后,可以重试请求。
我们是否有办法认识到我们正在NSURLSession
内找回登录页面并告诉completionHandler
我们是否真的回到了身份验证挑战中?或者NSURLSession
要求我们收到HTTP错误代码(401等)
答案 0 :(得分:4)
有几种可能性浮现在脑海中。
如果您正在使用NSURLSession
的委托再现,则可以通过NSURLSessionTaskDelegate
方法willPerformHTTPRedirection
检测重定向到身份验证失败页面。< / p>
您也可以通过检查任务currentRequest.URL
来检测重定向,并查看是否还发生了重定向。正如文档所说,currentRequest
&#34;通常与初始请求(originalRequest
)相同,除非服务器通过重定向到不同的URL来响应初始请求。&#34
假设RESTful服务通常不会返回HTML,您可以查看NSURLResponse
,确认它确实是NSHTTPURLResponse
子类,然后查看{ {1}}确认allHeaderFields
是否出现在回复的text/html
中。这显然只有在身份验证页面返回包含Content-Type
的{{1}}并且其他回复不包含的情况下才会有效(例如他们会Content-Type
或类似的事情)
无论如何,这可能看起来像:
text/html
其中,application/json
可能定义如下:
NSString *contentType = [self headerValueForKey:@"Content-Type" response:response];
if ([contentType rangeOfString:@"text/html"].location != NSNotFound) {
// handle it here
}
在最坏的情况下,您可以检测HTML响应并使用类似HPPLE的内容进行解析,并以编程方式检测身份验证HTML响应。
见Wenderlich的文章How to Parse HTML on iOS。
答案 1 :(得分:1)
您是否曾尝试将用户名和密码设置为NSMutableURLRequest的授权标头。
NSString *authorizationString = [[[NSString stringWithFormat:@"%@:%@",user, password] dataUsingEncoding:NSUTF8StringEncoding] base64Encoding];
[yourRequest setValue:[NSString stringWithFormat:@"Basic %@", authorizationString] forHTTPHeaderField:@"Authorization"];
这应该有效。
答案 2 :(得分:1)
身份验证挑战由40x响应中的WWW-Authenticate标头触发。
除非服务器响应包含WWW-Authenticate标头,否则URL加载系统类不会调用其委托来处理请求质询。其他身份验证类型(例如代理身份验证和TLS信任验证)不需要此标头。
不幸的是,上面提到的代理身份验证不适用于您的反向代理/加速器方案。
答案 3 :(得分:0)
您可以尝试使用HTML Parser库(例如https://github.com/nolanw/HTMLReader)。
然后在完成处理程序块中,您可以评估响应以检查它是否是HTML页面,以及它是否包含登录表单。
我不知道这个库,但我想你可以像这样使用它:
HTMLDocument *document = [HTMLDocument documentWithString:responseObjectFromServer];
HTMLNode *node = [document firstNodeMatchingSelector:@"form.login"];
if(node) {
// Perform second NSURLSession call with login data
}