NSURLConnection sendSynchronousRequest,需要在URL中进行身份验证

时间:2014-03-10 21:34:57

标签: php ios objective-c http http-authentication

从这个问题我已经实现了将文件上传到服务器:Upload File to Server

我正在阅读Apple文档以了解NSURLConnection sendSynchronousRequest方法的安全性,并且文档说如果文件需要身份验证,它将使用URL中的凭据。我的问题是,我如何要求身份验证?我假设它在服务器端。

1 个答案:

答案 0 :(得分:1)

有大量不同类型的身份验证。有关详细信息,请参阅 URL加载系统编程指南的Authentication Challenges and TLS Chain Validation部分。

但是,在回答您的问题时,是的,您可能希望在Web服务器上使用安全性,然后使用适当的凭据让您的iOS网络请求进行身份验证。如果您只是将您的脚趾浸入经过身份验证的请求的世界中,您应该从HTTP“基本”身份验证开始。 (还有许多其他类型的身份验证,但是通过所有这些身份验证超出了简单的Stack Overflow答案的范围。)

HTTP“基本”身份验证的实现包含两个组件:

  1. 在您要进入网站管理的服务器上,将用户ID和密码添加到包含您的Web服务的文件夹中(例如,您与我们共享的该链接中引用的PHP代码)。具体情况会有所不同,具体取决于您拥有的Web服务器。我的ISP提供了“控制面板”,在“安全”部分有一个名为“目录密码”的功能。您的Web服务器可能会有所不同,因此如果不明显,请与您的ISP联系。

  2. 在iOS方面,而不是sendSynchronousRequest(这是一个可怕的解决方案,无论如何;从不做同步网络请求),你想要使用基于委托的NSURLConnection除了标准didReceiveResponsedidReceiveDataconnectionDidFinishLoadingdidFailWithError方法,您还需要编写一个didReceiveAuthenticationChallenge方法,该方法提供您设置的用户标识和密码在前一步骤中。

  3. 在iOS方面,而不是sendSynchronousRequest,您希望这样做:

    [NSURLConnection connectionWithRequest:request delegate:self];
    

    然后实现以下委托方法:

    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    {
        if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
            int statusCode = [(NSHTTPURLResponse *)response statusCode];
            if (statusCode != 200) {
                NSLog(@"%s failed status code %d", __FUNCTION__, statusCode);
            }
        }
    
        self.responseData = [NSMutableData data];
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
        [self.responseData appendData:data];
    }
    
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
        // do whatever you want upon success
    
        NSLog(@"%s success; data = %@", __FUNCTION__, [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding]);
    }
    
    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    {
        // do whatever you want upon failure
    
        NSLog(@"%s: %@", __FUNCTION__, error);
    }
    
    -(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
    {
        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic]) {
            if ([challenge previousFailureCount] == 0) {
                NSURLCredential *credential = [NSURLCredential credentialWithUser:kUsername
                                                                         password:kPassword
                                                                      persistence:NSURLCredentialPersistenceForSession];
    
                [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
            }
            else
            {
                [[challenge sender] cancelAuthenticationChallenge:challenge];
    
                // inform the user that the user name and password
                // in the preferences are incorrect
    
                NSLog (@"failed authentication");
    
                // ...error will be handled by connection didFailWithError
            }
        }
    }
    

    显然,这假设您定义了responseData属性:

    @property (nonatomic, strong) NSMutableData *responseData;
    

    现在,我怀疑你正在热衷于所有这些代码的概念,以发送请求并验证该请求。但是,正确的HTTP级别身份验证需要这样的解决方案。像sendSynchronousRequest这样的便捷方法(你应该避免,无论如何)和sendAsynchronousRequest(这是更好的,但仍然不能处理这样的身份验证挑战)只是不能胜任这项任务。如果您不想编写所有这些代码,那么您可以考虑使用类似AFNetworking的库来执行所有这类代码(以及更多),并让您摆脱杂草处理这样的网络请求。

相关问题