我正在使用通过Restful服务连接到ASP.NET Web API的iOS应用程序。我想使用自定义委托来处理身份验证质询。但委托方法并没有被调用。
http请求在视图控制器中使用以下方法编写:
- (IBAction)test:(UIButton *)sender
{
//Get Bearer Token
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"BearerToken" accessGroup:nil];
NSString *bearerToken = [keychainItem objectForKey:(__bridge id)(kSecValueData)];
//Configure request
NSURL *url = [NSURL URLWithString:@"......"]; //Replace the .... with real IP Address
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"GET"];
[request setValue:[NSString stringWithFormat:@"Bearer %@", bearerToken] forHTTPHeaderField:@"Authorization"];
//Configure session
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AuthChallengeDelegate *authChallengeDel = [[AuthChallengeDelegate alloc] init];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
delegate:authChallengeDel
delegateQueue:nil];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
[task resume];
}
在AuthChallengeDelegate类中,我实现了以下方法:
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
{
NSLog(@"%@", response);
}
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition,
NSURLCredential *credential))completionHandler
{
NSLog(@"did receive challenge method called");
NSLog(@"%@", challenge.protectionSpace.authenticationMethod);
}
调用第一个方法(didReceiveResponse),响应状态代码为401,其中包含" Www-Authenticate" =标题字段中的承载。但是没有调用第二种方法(didReceiveChallenge)。这里的任何人都可以告诉我为什么没有这个?
(我使用Xcode 6并在iOS8中进行模拟)
感谢。
答案 0 :(得分:8)
重要提示:除非服务器响应包含WWW-Authenticate标头,否则URL加载系统类不会调用其委托来处理请求质询。
我们从中了解didReceiveChallenge
方法应该被称为 BUT ,只有当标题看起来像URLSession:task:didReceiveChallenge:completionHandler:
'WWW-Authenticate':'Basic'
我还没有找到任何解决方案如何处理基于令牌的身份验证,其中标头为'WWW-Authenticate':'Bearer'
,使用身份验证质询。
答案 1 :(得分:6)
NSURLSession的代表中有两个不同的挑战/响应处理程序。您正在实施的第一个是会话级别,基本上处理服务器级别的身份验证。来自the documentation:
对于会话级别的挑战 - NSURLAuthenticationMethodNTLM,NSURLAuthenticationMethodNegotiate,NSURLAuthenticationMethodClientCertificate或NSURLAuthenticationMethodServerTrust - NSURLSession对象调用会话委托的URLSession:didReceiveChallenge:completionHandler:方法。如果您的应用程序未提供会话委托方法,则NSURLSession对象将调用任务委托的URLSession:task:didReceiveChallenge:completionHandler:处理质询的方法。
对于非会话级别的挑战(所有其他挑战),NSURLSession对象调用会话委托的URLSession:task:didReceiveChallenge:completionHandler:处理挑战的方法。如果您的应用程序提供了会话委托,并且您需要处理身份验证,那么您必须在任务级别处理身份验证,或者提供一个显式调用每会话处理程序的任务级处理程序。 会话代理的URLSession:didReceiveChallenge:completionHandler:方法未针对非会话级别的挑战进行调用。
因此,您可能希望通过在委托对象中添加对NSURLSession 任务委托的协议支持来处理任务级别身份验证,并在任务级别提供处理程序,即
URLSession(_:task:didReceiveChallenge:completionHandler:)
。
答案 2 :(得分:2)
我知道此问题与iOS 8有关,但如果您使用的是iOS 9,请注意,NSAppTransportSecurity
中的Info.plist
密钥现在必须用于定位任何特定域名。< / p>
我遇到了完全相同的问题,并使用wireshark查看TLS网络层,以检查我所定位的图像服务器使用的TLS版本。
基于此,您可以将其添加到Info.plist
,这有望解决此问题
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>yourdomain.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
</dict>
</dict>
</dict>
答案 3 :(得分:2)
如果你写:
AuthChallengeDelegate *authChallengeDel = [[AuthChallengeDelegate alloc] init];
authChallengeDel是LOCAL,因此一旦退出方法就会释放。 所以把它变成一个属性
答案 4 :(得分:0)
在我的情况下,我认为这是重载方法,但是使用了错误的签名。
答案 5 :(得分:-1)
尝试更改委托:authChallengeDel委托:self