1

我正在使用我的内部 api 从我的服务器检索数据。我正在使用基本身份验证来实现这一点。由于 API 的性质,我没有在我的服务器代码上实现任何会话或任何其他内容,所以我将用户名和密码与我的所有请求一起发送。

因此,我不想为我正在使用的每个视图控制器实现 NSURLConnection 委托。因此,我创建了一个扩展 NSObject 的辅助类,并将其设置为 NSURLConnectionDelegate。

@interface HandlerClass : NSObject <NSURLConnectionDelegate>

我实现了我需要的每一个方法,我这样称呼它:

NSURL *URL = [NSURL URLWithString:@"https://url/ifuser/"];
NSLog(@"Connection ");

NSURLRequest *request = [NSURLRequest requestWithURL:URL
                                         cachePolicy:NSURLRequestReloadIgnoringCacheData
                                     timeoutInterval:30.0];

NSHTTPURLResponse *response;

HandlerClass *cc = [[HandlerClass alloc] init];

cc.username = self.username.text;
cc.password = self.password.text;

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:cc];

但是无论我尝试什么,我都无法从该代表那里获得数据响应数据。

我真的试图阅读互联网上的每一篇文章,包括 stackoverflow 和其他网站。每个解决方案都不需要身份验证。

但我只需要身份验证的解决方案。

谢谢。

~~~~~~~~~~~~~~~~~~~~~~~~~

编辑:我知道我犯了几个多余的错误。但我可以弄清楚做错了什么。我只需要使用 NSRunLoop 来实现我的目标。谢谢大家。

4

2 回答 2

1

这就是我所做的。我参考了这篇文章:Basic Authentication with a NSURLRequest in Cocoa Touch,它使用同步请求。这里异步用于请求。

ConnectionHandler.h

#import <Foundation/Foundation.h>

@interface ConnectionHandler : NSObject<NSURLConnectionDataDelegate>

@property(nonatomic, retain) NSString *username;
@property(nonatomic, retain) NSString *password;

- (void)start;

@end

在 ConnectionHandler.m

#import "ConnectionHandler.h"
#import "Base64.h"
@interface ConnectionHandler()
{
    NSMutableData *receivedData;
    NSURLConnection *connection;
}
@end
@implementation ConnectionHandler

- (id)init
{
    self = [super init];
    if (self) {
        receivedData = [[NSMutableData alloc] init];
    }
    return self;
}

- (void)start
{
    NSURL *url = [NSURL URLWithString:@"http://192.168.1.103/~will/"];

    NSError *myError = nil;

    // create a plaintext string in the format username:password
    NSMutableString *loginString = (NSMutableString*)[@"" stringByAppendingFormat:@"%@:%@", self.username, self.password];

    // employ the Base64 encoding above to encode the authentication tokens
    NSString *encodedLoginData = [Base64 encode:[loginString dataUsingEncoding:NSUTF8StringEncoding]];

    // create the contents of the header
    NSString *authHeader = [@"Basic " stringByAppendingFormat:@"%@", encodedLoginData];

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: url
                                                       cachePolicy: NSURLRequestReloadIgnoringCacheData
                                                   timeoutInterval: 3];

    // add the header to the request.  Here's the $$$!!!
    [request addValue:authHeader forHTTPHeaderField:@"Authorization"];

    // perform the reqeust
    NSURLResponse *response;

    connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    [connection start];

}

//a simple request may receive several response, when a new response receive, the previous received should be reset.
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    [receivedData setLength:0];
}
//a connection may receive data several time, append the received data to existing data
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [receivedData appendData:data];
}


- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    connection = nil;
    receivedData = nil;

    NSLog(@"Connection failed! Error - %@ %@",
      [error localizedDescription],
      [[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
}


- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{

    NSLog(@"succeeded  %d byte received",[receivedData length]);
    receivedData = nil;
    connection = nil;
}
@end

Base64.m

#import "Base64.h"

static char *alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

@implementation Base64

+(NSString *)encode:(NSData *)plainText {
    int encodedLength = (4 * (([plainText length] / 3) + (1 - (3 - ([plainText length] % 3)) / 3))) + 1;
    unsigned char *outputBuffer = malloc(encodedLength);
    unsigned char *inputBuffer = (unsigned char *)[plainText bytes];

    NSInteger i;
    NSInteger j = 0;
    int remain;

    for(i = 0; i < [plainText length]; i += 3) {
        remain = [plainText length] - i;

        outputBuffer[j++] = alphabet[(inputBuffer[i] & 0xFC) >> 2];
        outputBuffer[j++] = alphabet[((inputBuffer[i] & 0x03) << 4) |
                                 ((remain > 1) ? ((inputBuffer[i + 1] & 0xF0) >> 4): 0)];

        if(remain > 1)
            outputBuffer[j++] = alphabet[((inputBuffer[i + 1] & 0x0F) << 2)
                                     | ((remain > 2) ? ((inputBuffer[i + 2] & 0xC0) >> 6) : 0)];
        else
            outputBuffer[j++] = '=';

        if(remain > 2)
            outputBuffer[j++] = alphabet[inputBuffer[i + 2] & 0x3F];
        else
            outputBuffer[j++] = '=';
    }

    outputBuffer[j] = 0;

    NSString *result = [NSString stringWithCString:outputBuffer length:strlen(outputBuffer)];
    free(outputBuffer);

    return result;
}

@end

在视图控制器中

- (void)viewDidLoad
{
    [super viewDidLoad];
    ConnectionHandler *connectionHandler = [[ConnectionHandler alloc] init];
    connectionHandler.username = @"username";
    connectionHandler.password = @"password";
    [connectionHandler start];

}
于 2013-02-10T16:21:36.123 回答
0

我经历了类似的要求,请查看发布到此问题的解决方案

该解决方案使用完成块,并且可以很好地从另一个(处理程序)类中实现的委托方法中检索信息。

于 2014-04-15T07:25:30.920 回答