আইওএসে এনএসআরএল সংযোগ এবং বেসিক HTTP প্রমাণীকরণ


85

আমার GET HTTP requestবেসিকের সাথে প্রাথমিক হতে হবে Authentication। এটি প্রথমবারের মতো অনুরোধটি সার্ভারে প্রেরণ করা হবে এবং আমার কাছে ইতিমধ্যে username & passwordতাই অনুমোদনের জন্য সার্ভারের কোনও চ্যালেঞ্জের দরকার নেই।

প্রথম প্রশ্ন:

  1. না NSURLConnectionবুনিয়াদি প্রমাণীকরণ করতে সমলয় হিসাবে সেট করা থাকতে হবে? এই পোস্টের উত্তর অনুসারে , দেখে মনে হচ্ছে আপনি যদি অ্যাসিঙ্ক রুটটি বেছে নেন তবে আপনি বেসিক অথ করতে পারবেন না।

  2. GET requestচ্যালেঞ্জের প্রতিক্রিয়ার প্রয়োজন ছাড়াই এমন কোনও নমুনা কোডের কথা যে কেউ বেসিক লেখাকে চিত্রিত করে ? অ্যাপলের ডকুমেন্টেশন একটি উদাহরণ দেখায় তবে কেবল সার্ভার ক্লায়েন্টকে চ্যালেঞ্জ অনুরোধ জারি করার পরে।

আমি এসডিকে এক ধরণের নতুন নেটওয়ার্কিং অংশ এবং এই কাজটি করার জন্য আমার অন্যান্য ক্লাসগুলির মধ্যে কোনটি ব্যবহার করা উচিত তা আমি নিশ্চিত নই। (আমি NSURLCredentialক্লাসটি দেখছি তবে মনে NSURLAuthenticationChallengeহয় ক্লায়েন্টটি সার্ভার থেকে অনুমোদিত উত্সের জন্য অনুরোধ করার পরেই এটি ব্যবহার করা হয়েছে)।

উত্তর:


132

আমি এমজিটিউইটারইঙ্গিনের সাথে একটি অ্যাসিঙ্ক্রোনাস সংযোগ ব্যবহার করছি এবং এটি 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"];

আমি বিশ্বাস করি না যে এই পদ্ধতিটির জন্য চ্যালেঞ্জের লুপটি অতিক্রম করা প্রয়োজন তবে আমি ভুল হতে পারি


4
আমি সেই অংশটি লিখিনি, এটি এনজিডাটাতে যুক্ত একটি বিভাগ থেকে এমজিটিউইটারইঙ্গিনের মাত্র একটি অংশ। এনএসডাটা + বেস64৪৪৪.৪ মিঃ এখানে দেখুন: github.com/ctshryock/MGTwitterEngine
ক্যাটসবি

7
[authData base64EncodedString]বেস64 -এনকোডিংয়ের জন্য ( ) এনএসডিটা + বেস 64 এবং আপনার এমকোড-প্রজেক্টে ম্যাট গ্যালাগার থেকে .m ফাইল যুক্ত করুন ( ম্যাক এবং আইফোনে বেস64 এনকোডিং বিকল্পগুলি )।
Elim

4
এনএসএএসসিআইআইএসটিআরসিডিং এনকোডিং নন-ইউএসসিআই ব্যবহারকারীর নাম বা পাসওয়ার্ডকে দূষিত করবে। পরিবর্তে এনএসইউটিএফ 8 স্ট্রিংএকনডিংটি ব্যবহার করুন
ডার্ক ডি কোক

4
বেস 64 এনকোডিং উইথলাইনলেংথের এনএসডিটা-তে 2014 নেই। পরিবর্তে বেস 64 এনকোডিং ব্যবহার করুন।
সাইকেল 23

11
base64Encodingআইওএস 7.০ এবং ওএস এক্স ১০.৯-এর পরে @ বাইকস্টারকে অবমূল্যায়ন করা হয়েছে। আমি [authData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]পরিবর্তে ব্যবহার । এছাড়াও উপলব্ধ `NSDataBase64 এনকোডিং 64CharacterLineLength` বাNSDataBase64Encoding76CharacterLineLength
ডার্ক

80

এমনকি প্রশ্নের উত্তর দেওয়া হয়েছে, আমি সমাধানটি উপস্থাপন করতে চাই, যার বাহ্যিক স্তরের প্রয়োজন নেই, আমি অন্য একটি থ্রেডে পেয়েছি:

// 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 {
    ...
}

9
এটি অন্যান্য সমাধানগুলির মতো পুরোপুরি এক নয়: এই সার্ভারটি প্রথমে যোগাযোগ করে, একটি 401 প্রতিক্রিয়া গ্রহণ করে, তারপরে সঠিক শংসাপত্রগুলির সাথে প্রতিক্রিয়া জানায়। সুতরাং আপনি একটি বৃত্তাকার ট্রিপ নষ্ট করছি। উল্টো দিকে, আপনার কোড অন্যান্য চ্যালেঞ্জগুলি যেমন HTTP ডাইজেস্ট আথ পরিচালনা করবে। এটি একটি বাণিজ্য বন্ধ।
বেনজাদো

4
যাইহোক, এটি করার এটি "সঠিক উপায়"। অন্যান্য সমস্ত উপায় শর্টকাট।
লাগাগ

4
অনেক ধন্যবাদ! @ মূসগুম্মি
লে

@ অন্যথায় আমি এটি ব্যবহার করেছি তবে কিছু কারণে রেসিভআউটেনটিকেশন চ্যালেঞ্জ বলা হচ্ছে না এবং আমি সাইট থেকে 403 অ্যাক্সেস প্রত্যাখাত বার্তা পাচ্ছি। কেউ কি জানেন যে ভুল হয়েছে?
ডিক্লান ম্যাককেনা

হ্যাঁ, এটি করার একমাত্র সঠিক উপায়। এবং এটি কেবল প্রথমবার 401 প্রতিক্রিয়া সৃষ্টি করে causes পরবর্তী একই অনুরোধের অনুরোধগুলি প্রমাণীকরণের সাথে প্রেরণ করা হয়।
ডিগাটউড

12

এখানে কোনও তৃতীয় পক্ষের জড়িত না থাকার একটি বিশদ উত্তর:

এখানে চেক করুন:

//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];
      }
}]

দয়া করে আমাকে এই সম্পর্কে আপনার প্রতিক্রিয়া জানান।

ধন্যবাদ


NSData কে NSString এ রূপান্তর করতে আপনি যে পদ্ধতিটি বেস 64 এনকডিংটি ব্যবহার করছেন সেটি এখন অবচয় করা হয়েছে: - (NSString *)base64Encoding NS_DEPRECATED(10_6, 10_9, 4_0, 7_0);পরিবর্তে NSDataBase64 এড্ডিং বিভাগটি ব্যবহার করা আরও ভাল।
বেন

7

আপনি যদি পুরো এমজিটিভিটারইঙ্গিনকে পুরোটা আমদানি করতে না চান এবং আপনি একটি অ্যাসিনক্রোনাস অনুরোধটি না করেন তবে আপনি http://www.chrisumbel.com/article/basic_authentication_iphone_cocoa_touch ব্যবহার করতে পারেন

বেস 64 ব্যবহারকারীর নাম এবং পাসওয়ার্ড এনকোড করতে তাই প্রতিস্থাপন

NSString *authValue = [NSString stringWithFormat:@"Basic %@", [authData base64EncodingWithLineLength:80]];

সঙ্গে

NSString *encodedLoginData = [Base64 encode:[loginString dataUsingEncoding:NSUTF8StringEncoding]];

পরে

আপনাকে নিম্নলিখিত ফাইলটি অন্তর্ভুক্ত করতে হবে

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

3

যেহেতু এনএসডিটা :: ডেটা ইউজিং এনকোডিং অবমূল্যায়ন করা হয়েছে (ios 7.0), আপনি এই সমাধানটি ব্যবহার করতে পারেন:

// 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"];

1

আপনি যদি আপনার সংযোগের জন্য জিটিএমএইচটিটিপিফ্যাচার ব্যবহার করেন তবে বুনিয়াদি প্রমাণীকরণও যথেষ্ট সহজ। আনতে শুরু করার আগে আপনার পক্ষে কেবল ফিচারটিকে শংসাপত্র সরবরাহ করতে হবে।

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:)];

0

আপনি কি আমাকে বলতে পারবেন আপনার উদাহরণ কোডটিতে এনকোডিং লাইনের দৈর্ঘ্য 80 টি সীমাবদ্ধ করার পিছনে কারণ কী? আমি ভেবেছিলাম যে এইচটিটিপি শিরোনামগুলির সর্বোচ্চ দৈর্ঘ্য 4k এর মতো কিছু রয়েছে (অথবা সম্ভবত কিছু সার্ভারের চেয়ে কিছু বেশি সময় নেয় না)। - জাস্টিন গ্যালজিক 29 ডিসেম্বর '09 এ 17:29 এ

এটি ৮০-এর মধ্যে সীমাবদ্ধ নয়, এটি এনএসডাটা + বেস .h৪.৪ / মি তে বেস বেস base৪ এনকোডিং উইথলাইনলেন্থ পদ্ধতির একটি বিকল্প, যেখানে আপনি আপনার এনকোডযুক্ত স্ট্রিংটিকে একাধিক লাইনে বিভক্ত করতে পারেন, যা এনএনটিপি সংক্রমণের মতো অন্যান্য অ্যাপ্লিকেশনের জন্য দরকারী। আমি বিশ্বাস করি যে বেশিরভাগ ব্যবহারকারীর / পাসওয়ার্ডের এনকোডযুক্ত ফলাফলকে এক লাইনে রাখার জন্য যথেষ্ট পরিমাণে দৈর্ঘ্য হিসাবে টুইটার ইঞ্জিন লেখক 80 টি পছন্দ করেছেন।


0

আপনি এএফ নেটওয়ার্কিং (এটি ওপেনসোর্স) ব্যবহার করতে পারেন , এখানে কোডটি আমার পক্ষে কাজ করেছে। এই কোডটি মৌলিক প্রমাণীকরণের সাথে ফাইল পাঠায়। কেবল url, ইমেল এবং পাসওয়ার্ড পরিবর্তন করুন change

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];
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.