iOS의 NSURLConnection 및 기본 HTTP 인증
GET HTTP request
Basic 으로 이니셜을 호출해야합니다 Authentication
. 이것은 요청이 서버로 처음 전송되는 것이며 이미 username & password
서버에서 인증을 요청할 필요가 없습니다.
첫 번째 질문 :
않습니다
NSURLConnection
기본 인증을 수행하는 동기로 설정되어야한다? 이 게시물 의 답변에 따르면 비동기 경로를 선택하면 기본 인증을 할 수없는 것 같습니다.누구든지
GET request
챌린지 응답없이 기본 인증을 설명하는 샘플 코드를 알고 있습니까? Apple의 문서 에 예제가 나와 있지만 서버가 클라이언트에 챌린지 요청을 보낸 후에 만 해당됩니다.
저는 SDK의 네트워킹 부분이 새로워졌고이 작업을 수행하기 위해 사용해야하는 다른 클래스를 잘 모르겠습니다. ( NSURLCredential
클래스가 보이지만 NSURLAuthenticationChallenge
클라이언트가 서버에서 인증 된 리소스를 요청한 후에 만 사용되는 것 같습니다 .)
MGTwitterEngine 과 비동기 연결을 사용하고 있으며 다음 과 같이 NSMutableURLRequest
( theRequest
)에 권한을 설정합니다 .
NSString *authStr = [NSString stringWithFormat:@"%@:%@", [self username], [self password]];
NSData *authData = [authStr dataUsingEncoding:NSASCIIStringEncoding];
NSString *authValue = [NSString stringWithFormat:@"Basic %@", [authData base64EncodingWithLineLength:80]];
[theRequest setValue:authValue forHTTPHeaderField:@"Authorization"];
이 방법이 챌린지 루프를 거쳐야한다고 생각하지는 않지만 틀릴 수 있습니다.
질문에 대답해도 외부 라이브러리가 필요하지 않은 솔루션을 제시하고 싶습니다. 다른 스레드에서 찾았습니다.
// Setup NSURLConnection
NSURL *URL = [NSURL URLWithString:url];
NSURLRequest *request = [NSURLRequest requestWithURL:URL
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:30.0];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
[connection release];
// NSURLConnection Delegates
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
if ([challenge previousFailureCount] == 0) {
NSLog(@"received authentication challenge");
NSURLCredential *newCredential = [NSURLCredential credentialWithUser:@"USER"
password:@"PASSWORD"
persistence:NSURLCredentialPersistenceForSession];
NSLog(@"credential created");
[[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
NSLog(@"responded to authentication challenge");
}
else {
NSLog(@"previous authentication failure");
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
...
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
...
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
...
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
...
}
다음은 타사가 관여하지 않은 자세한 답변입니다.
여기에서 확인하십시오 :
//username and password value
NSString *username = @“your_username”;
NSString *password = @“your_password”;
//HTTP Basic Authentication
NSString *authenticationString = [NSString stringWithFormat:@"%@:%@", username, password]];
NSData *authenticationData = [authenticationString dataUsingEncoding:NSASCIIStringEncoding];
NSString *authenticationValue = [authenticationData base64Encoding];
//Set up your request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.your-api.com/“]];
// Set your user login credentials
[request setValue:[NSString stringWithFormat:@"Basic %@", authenticationValue] forHTTPHeaderField:@"Authorization"];
// Send your request asynchronously
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *responseCode, NSData *responseData, NSError *responseError) {
if ([responseData length] > 0 && responseError == nil){
//logic here
}else if ([responseData length] == 0 && responseError == nil){
NSLog(@"data error: %@", responseError);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"Error accessing the data" delegate:nil cancelButtonTitle:@"Close" otherButtonTitles:nil];
[alert show];
[alert release];
}else if (responseError != nil && responseError.code == NSURLErrorTimedOut){
NSLog(@"data timeout: %@”, NSURLErrorTimedOut);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"connection timeout" delegate:nil cancelButtonTitle:@"Close" otherButtonTitles:nil];
[alert show];
[alert release];
}else if (responseError != nil){
NSLog(@"data download error: %@”,responseError);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"data download error" delegate:nil cancelButtonTitle:@"Close" otherButtonTitles:nil];
[alert show];
[alert release];
}
}]
이에 대한 귀하의 의견을 알려주십시오.
감사
If you don't want to import the whole of MGTwitterEngine and you aren't doing an asynchronous request Then you can use http://www.chrisumbel.com/article/basic_authentication_iphone_cocoa_touch
To base64 encode the Username and password So replace
NSString *authValue = [NSString stringWithFormat:@"Basic %@", [authData base64EncodingWithLineLength:80]];
with
NSString *encodedLoginData = [Base64 encode:[loginString dataUsingEncoding:NSUTF8StringEncoding]];
after
you will need to include the following file
static char *alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@implementation Base64
+(NSString *)encode:(NSData *)plainText {
int encodedLength = (((([plainText length] % 3) + [plainText length]) / 3) * 4) + 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
Since NSData::dataUsingEncoding is deprecated (ios 7.0), you could use this solution:
// Forming string with credentials 'myusername:mypassword'
NSString *authStr = [NSString stringWithFormat:@"%@:%@", username, password];
// Getting data from it
NSData *authData = [authStr dataUsingEncoding:NSASCIIStringEncoding];
// Encoding data with base64 and converting back to NSString
NSString* authStrData = [[NSString alloc] initWithData:[authData base64EncodedDataWithOptions:NSDataBase64EncodingEndLineWithLineFeed] encoding:NSASCIIStringEncoding];
// Forming Basic Authorization string Header
NSString *authValue = [NSString stringWithFormat:@"Basic %@", authStrData];
// Assigning it to request
[request setValue:authValue forHTTPHeaderField:@"Authorization"];
If you are using GTMHTTPFetcher for your connection, basic authentication is fairly easy as well. You simply need to provide the credential to the fetcher before beginning the fetch.
NSString * urlString = @"http://www.testurl.com/";
NSURL * url = [NSURL URLWithString:urlString];
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
NSURLCredential * credential = [NSURLCredential credentialWithUser:@"username" password:@"password" persistence:NSURLCredentialPersistenceForSession];
GTMHTTPFetcher * gFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
gFetcher.credential = credential;
[gFetcher beginFetchWithDelegate:self didFinishSelector:@selector(fetchCompleted:withData:andError:)];
Can you tell me what's the reason behind limiting the encoding line length to 80 in your example code? I thought that HTTP headers have a max length of something like 4k (or maybe some servers don't take anything longer than that). – Justin Galzic Dec 29 '09 at 17:29
It is not limiting to 80, it is an option of the method base64EncodingWithLineLength in NSData+Base64.h/m, where you can split your encoded string into multiple lines, which is useful for other application, such as nntp transmission. I believe 80 is chosen by the twitter engine author to be a length big enough to accommodate most user/password encoded result to one line.
You can use AFNetworking (it is opensource), here is code that worked for me. This code sends file with basic authentication. Just change url, email and password.
NSString *serverUrl = [NSString stringWithFormat:@"http://www.yoursite.com/uploadlink", profile.host];
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:serverUrl parameters:nil error:nil];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
// Forming string with credentials 'myusername:mypassword'
NSString *authStr = [NSString stringWithFormat:@"%@:%@", email, emailPassword];
// Getting data from it
NSData *authData = [authStr dataUsingEncoding:NSASCIIStringEncoding];
// Encoding data with base64 and converting back to NSString
NSString* authStrData = [[NSString alloc] initWithData:[authData base64EncodedDataWithOptions:NSDataBase64EncodingEndLineWithLineFeed] encoding:NSASCIIStringEncoding];
// Forming Basic Authorization string Header
NSString *authValue = [NSString stringWithFormat:@"Basic %@", authStrData];
// Assigning it to request
[request setValue:authValue forHTTPHeaderField:@"Authorization"];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
NSURL *filePath = [NSURL fileURLWithPath:[url path]];
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:^(NSProgress * _Nonnull uploadProgress) {
// This is not called back on the main queue.
// You are responsible for dispatching to the main queue for UI updates
dispatch_async(dispatch_get_main_queue(), ^{
//Update the progress view
LLog(@"progres increase... %@ , fraction: %f", uploadProgress.debugDescription, uploadProgress.fractionCompleted);
});
} completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
NSLog(@"Success: %@ %@", response, responseObject);
}
}];
[uploadTask resume];
참고URL : https://stackoverflow.com/questions/1973325/nsurlconnection-and-basic-http-authentication-in-ios
'IT story' 카테고리의 다른 글
C #에서 데이터를 문자열에서 long으로 어떻게 변환 할 수 있습니까? (0) | 2020.09.17 |
---|---|
AppDelegate 인스턴스 변수 참조 (0) | 2020.09.17 |
JQuery 또는 JavaScript : 앵커 태그 하이퍼 링크를 클릭하는 동안 Shift 키를 눌렀는지 확인하는 방법은 무엇입니까? (0) | 2020.09.17 |
jQuery UI datepicker에서 날짜를 얻는 방법 (0) | 2020.09.17 |
'System.Net.Http.HttpContent'에 'ReadAsAsync'에 대한 정의가없고 확장 메서드가 없습니다. (0) | 2020.09.17 |