एक बिना प्रमाणित प्रमाण पत्र के एसएसएल से जुड़ने के लिए NSURLConnection का उपयोग कैसे करें?


300

SSL वेबपेज से जुड़ने के लिए मेरे पास निम्न सरल कोड हैं

NSMutableURLRequest *urlRequest=[NSMutableURLRequest requestWithURL:url];
[ NSURLConnection sendSynchronousRequest: urlRequest returningResponse: nil error: &error ];

सिवाय इसके कि कोई त्रुटि देता है यदि प्रमाणपत्र एक स्व-हस्ताक्षरित है तो Error Domain=NSURLErrorDomain Code=-1202 UserInfo=0xd29930 "untrusted server certificate".क्या इसे वैसे भी कनेक्शन स्वीकार करने के लिए निर्धारित करने का एक तरीका है (जैसे एक ब्राउज़र में आप स्वीकार कर सकते हैं) या इसे बायपास करने का एक तरीका है?

जवाबों:


415

इसे पूरा करने के लिए एक समर्थित एपीआई है! अपने NSURLConnectionप्रतिनिधि को कुछ इस तरह जोड़ें :

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
  return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
  if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
    if ([trustedHosts containsObject:challenge.protectionSpace.host])
      [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];

  [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}

ध्यान दें कि connection:didReceiveAuthenticationChallenge:चुनौती के लिए अपना संदेश भेज सकते हैं। (बहुत) बाद में, यदि आवश्यक हो, तो उपयोगकर्ता को एक संवाद बॉक्स पेश करने के बाद।


31
बहुत बहुत धन्यवाद, यह पूरी तरह से काम करता है। यदि आप किसी भी https साइट को स्वीकार करना चाहते हैं, तो दो ifs को हटा दें और didReceiveAuthentificationChallenge कॉलबैक में केवल उपयोग भाग को रखें।
योनेल

19
एक विश्वस्त क्या है, जहाँ n को किस प्रकार परिभाषित किया गया है
Ameya

7
Ameya, यह NSString ऑब्जेक्ट्स का NSArray होगा। तार @ "google.com" जैसे होस्ट नाम हैं।
विलियम डेनिस

19
यह कोड अच्छी तरह से काम करता है। लेकिन ध्यान दें कि वैध प्रमाणपत्र होने का पूरा बिंदु मानव-मध्य हमलों को रोकने के लिए है। इसलिए जागरूक रहें यदि आप इस कोड का उपयोग करते हैं, तो कोई तथाकथित "विश्वसनीय होस्ट" को खराब कर सकता है। आपको अभी भी एसएसएल की डेटा एन्क्रिप्शन सुविधाएँ मिलती हैं, लेकिन आप सत्यापन सुविधाओं की मेजबानी पहचान खो देते हैं।
विलियम डेनिस

42
इन विधियों को अब iOS 5.0 और Mac OS X 10.6 के रूप में पदावनत माना जाता है। इसके -(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challengeबजाय विधि का उपयोग किया जाना चाहिए।
एंड्रयू आर।

36

यदि आप निजी APIs का उपयोग करने में असमर्थ (या असमर्थ) हैं, तो ASIHTTPRequest नामक एक खुला स्रोत (BSD लाइसेंस) पुस्तकालय है जो निचले स्तर के आसपास एक आवरण प्रदान करता है CFNetwork APIs। उन्होंने हाल ही HTTPS connectionsमें -setValidatesSecureCertificate:एपीआई के साथ स्व-हस्ताक्षरित या अविश्वसनीय प्रमाणपत्रों का उपयोग करने की अनुमति देने की क्षमता का परिचय दिया । यदि आप पूरी लाइब्रेरी में नहीं जाना चाहते हैं, तो आप स्रोत को उसी कार्यक्षमता को लागू करने के लिए संदर्भ के रूप में उपयोग कर सकते हैं।


2
टिम, आप अपने आप को अन्य कारणों से async का उपयोग करने के लिए इच्छुक पा सकते हैं (जैसे कि एक प्रगति बार दिखाने में सक्षम होना), मैं सभी के लिए खोजता हूं लेकिन अनुरोधों का सबसे सरल तरीका यही है कि मैं जाता हूं। तो हो सकता है कि आपको अभी Async को लागू करना चाहिए और बाद में परेशानी से बचाना चाहिए।
विलियम डेनिस

कार्यान्वयन के लिए इसे देखें (लेकिन उपयोग करें [r setValidatesSecureCertificate: NO];): stackoverflow.com/questions/7657786/…
सैम ब्रोडकिन

क्षमा करें कि मैं इस विषय को वापस ले आया। लेकिन जब से iOS 5 ने ARC फीचर पेश किया है। अब मैं यह काम कैसे कर सकता हूं?
मेल्विन लाई

क्या आप इसे देख सकते हैं: stackoverflow.com/q/56627757/1364053
nr5

33

आदर्श रूप से, केवल दो परिदृश्य होने चाहिए जब एक आईओएस आवेदन को एक गैर-विश्वसनीय प्रमाण पत्र स्वीकार करने की आवश्यकता होगी।

परिदृश्य A: आप एक परीक्षण वातावरण से जुड़े हैं जो स्व-हस्ताक्षरित प्रमाणपत्र का उपयोग कर रहा है।

परिदृश्य B: आप प्रॉक्सी HTTPSका उपयोग कर ट्रैफ़िक प्राप्त कर रहे हैं MITM Proxy like Burp Suite, Fiddler, OWASP ZAP, etc., प्रॉक्सी एक स्व-हस्ताक्षरित CA द्वारा हस्ताक्षरित प्रमाणपत्र लौटाएगा, ताकि प्रॉक्सी HTTPSट्रैफ़िक को कैप्चर करने में सक्षम हो ।

उत्पादन होस्ट को स्पष्ट कारणों के लिए कभी भी गैर-विश्वसनीय प्रमाण पत्र का उपयोग नहीं करना चाहिए ।

यदि आपके पास iOS सिम्युलेटर की आवश्यकता है, तो परीक्षण उद्देश्यों के लिए एक गैर-विश्वसनीय प्रमाण पत्र स्वीकार करें यह अत्यधिक अनुशंसित है कि आप NSURLConnectionएपीआई द्वारा प्रदान किए गए प्रमाण पत्र सत्यापन में निर्मित अक्षम करने के लिए एप्लिकेशन लॉजिक को न बदलें । यदि इस तर्क को हटाए बिना आवेदन जनता के लिए जारी किया जाता है, तो यह बीच-बीच में होने वाले हमलों के लिए अतिसंवेदनशील होगा।

परीक्षण प्रयोजनों के लिए बिना विश्वसनीय प्रमाण पत्र स्वीकार करने का अनुशंसित तरीका प्रमाणपत्र प्राधिकरण (सीए) प्रमाणपत्र आयात करना है जिसने आपके आईओएस सिम्युलेटर या आईओएस डिवाइस पर प्रमाण पत्र पर हस्ताक्षर किए हैं। मैंने एक त्वरित ब्लॉग पोस्ट लिखी है जो यह प्रदर्शित करता है कि यह कैसे करना है जिस पर एक आईओएस सिम्युलेटर है:

आईओएस सिम्युलेटर का उपयोग करते हुए अविश्वसनीय प्रमाणपत्र स्वीकार करना


1
बहुत बढ़िया सामान आदमी। मैं मानता हूं, किसी भी अविश्वसनीय प्रमाण पत्र को स्वीकार करने के लिए इस विशेष एप्लिकेशन तर्क को अक्षम करने के बारे में भूलना बहुत आसान है।
टॉमाज़

"आदर्श रूप से, केवल दो परिदृश्य होने चाहिए जब एक आईओएस एप्लिकेशन को एक गैर-विश्वसनीय प्रमाणपत्र स्वीकार करने की आवश्यकता होगी।" - सर्टिफिकेट को पिन करते समय 'दावा' किए गए अच्छे सर्टिफिकेट को अस्वीकार करने के बारे में कैसे? Confer: डिग्नोटार (pwn'd) और ट्रस्टवेव (मिटम प्रसिद्धि)।
jww

कोड निकालने के लिए भूल जाने के बारे में आपके कथन से पूरी तरह सहमत हैं। विडंबना यह है कि स्व-हस्ताक्षरित समारोहों को स्वीकार करने के लिए सिम्युलेटर प्राप्त करने की तुलना में कोड में यह बदलाव करना बहुत आसान है।
देवियो १

12

NSURLRequestके पास एक निजी तरीका है setAllowsAnyHTTPSCertificate:forHost:, जिसे आप जैसा चाहें वैसा ही करेंगे। आप किसी श्रेणी के माध्यम से allowsAnyHTTPSCertificateForHost:विधि को परिभाषित कर सकते हैं NSURLRequest, और इसे YESउस होस्ट के लिए वापस सेट कर सकते हैं जिसे आप ओवरराइड करना चाहते हैं।


अनिर्दिष्ट एपीआई के बारे में सामान्य बातें लागू होती हैं ... लेकिन यह जानना संभव है कि यह संभव है।
स्टीफन डार्लिंगटन

हाँ, बिल्कुल। मैंने एक और उत्तर जोड़ा है जिसमें निजी APIs का उपयोग शामिल नहीं है।
नाथन डी ने

क्या आप "NSURLConnection sendSynchronousRequest:" का उपयोग करते समय काम करते हैं?
टिम बुथ

11

स्वीकार किए गए उत्तर के पूरक के लिए, बहुत बेहतर सुरक्षा के लिए, आप अपने सर्वर प्रमाणपत्र या अपने स्वयं के रूट CA प्रमाणपत्र को चाबी का गुच्छा ( https://stackoverflow.com/a/9941559/1432048 ) में जोड़ सकते हैं , हालांकि अकेले ऐसा करने से NSURLConnection नहीं होगा अपने स्व-हस्ताक्षरित सर्वर को स्वचालित रूप से प्रमाणित करें। आपको अभी भी नीचे दिए गए कोड को अपने NSURLConnection प्रतिनिधि में जोड़ने की आवश्यकता है, इसे Apple नमूना कोड AdvancedURLConnections से कॉपी किया गया है , और आपको अपनी परियोजनाओं में Apple नमूना कोड से दो फ़ाइलें (क्रेडेंशियल, क्रेडेंशियल) जोड़ने की आवश्यकता है।

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
//        if ([trustedHosts containsObject:challenge.protectionSpace.host])

    OSStatus                err;
    NSURLProtectionSpace *  protectionSpace;
    SecTrustRef             trust;
    SecTrustResultType      trustResult;
    BOOL                    trusted;

    protectionSpace = [challenge protectionSpace];
    assert(protectionSpace != nil);

    trust = [protectionSpace serverTrust];
    assert(trust != NULL);
    err = SecTrustEvaluate(trust, &trustResult);
    trusted = (err == noErr) && ((trustResult == kSecTrustResultProceed) || (trustResult == kSecTrustResultUnspecified));

    // If that fails, apply our certificates as anchors and see if that helps.
    //
    // It's perfectly acceptable to apply all of our certificates to the SecTrust
    // object, and let the SecTrust object sort out the mess.  Of course, this assumes
    // that the user trusts all certificates equally in all situations, which is implicit
    // in our user interface; you could provide a more sophisticated user interface
    // to allow the user to trust certain certificates for certain sites and so on).

    if ( ! trusted ) {
        err = SecTrustSetAnchorCertificates(trust, (CFArrayRef) [Credentials sharedCredentials].certificates);
        if (err == noErr) {
            err = SecTrustEvaluate(trust, &trustResult);
        }
        trusted = (err == noErr) && ((trustResult == kSecTrustResultProceed) || (trustResult == kSecTrustResultUnspecified));
    }
    if(trusted)
        [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}

[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}

10

मैं इसके लिए कोई श्रेय नहीं ले सकता, लेकिन इस एक को मैंने अपनी जरूरतों के लिए बहुत अच्छा काम किया। shouldAllowSelfSignedCertमेरा BOOLचर है बस अपने NSURLConnectionप्रतिनिधि को जोड़ें और आपको प्रति कनेक्शन के आधार पर एक त्वरित बाईपास के लिए रॉकिन होना चाहिए।

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)space {
     if([[space authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust]) {
          if(shouldAllowSelfSignedCert) {
               return YES; // Self-signed cert will be accepted
          } else {
               return NO;  // Self-signed cert will be rejected
          }
          // Note: it doesn't seem to matter what you return for a proper SSL cert
          //       only self-signed certs
     }
     // If no other authentication is required, return NO for everything else
     // Otherwise maybe YES for NSURLAuthenticationMethodDefault and etc.
     return NO;
}

10

IOS 9 में, SSL कनेक्शन सभी अमान्य या स्व-हस्ताक्षरित प्रमाणपत्रों के लिए विफल हो जाएगा। यह iOS 9.0 या उसके बाद और OS X 10.11 और बाद के नए ऐप ट्रांसपोर्ट सिक्योरिटी फ़ीचर का डिफ़ॉल्ट व्यवहार है ।

आप में इस व्यवहार को ओवरराइड कर सकते हैं Info.plistकी स्थापना करके, NSAllowsArbitraryLoadsकरने के लिए YESमें NSAppTransportSecurityशब्दकोश। हालाँकि, मैं इस सेटिंग को केवल परीक्षण उद्देश्यों के लिए ओवरराइड करने की सलाह देता हूं।

यहां छवि विवरण दर्ज करें

जानकारी के लिए ऐप ट्रांसपोर्ट टेक्नो यहां देखें


एकमात्र समाधान मेरे लिए काम किया, मेरे पास मेरी जरूरतों के अनुरूप फायरबेस ढांचे को बदलने का कोई तरीका नहीं है, जिसने इसे हल किया, धन्यवाद!
Yitzchak

अब मैंने देखा कि Google NSAllowArbiteathLoads = Admob (फायरबेस में) के लिए YES माँगता है। firebase.google.com/docs/admob/ios/ios9
Yitzchak

6

नाथन डे व्रीस द्वारा पोस्ट किया गया श्रेणी वर्कअराउंड AppStore प्राइवेट एपीआई चेक पास करेगा, और उन मामलों में उपयोगी है, जहां आपके पास NSUrlConnectionऑब्जेक्ट का नियंत्रण नहीं है । एक उदाहरण वह है NSXMLParserजो आपके द्वारा आपूर्ति किए गए URL को खोल देगा, लेकिन NSURLRequestया उजागर नहीं करता है NSURLConnection

IOS 4 में वर्कअराउंड अभी भी काम कर रहा है, लेकिन केवल डिवाइस पर, सिम्युलेटर allowsAnyHTTPSCertificateForHost:अब विधि को लागू नहीं करता है ।


6

आपको NSURLConnectionDelegateHTTPS कनेक्शन की अनुमति देने के लिए उपयोग करना है और iOS8 के साथ नए कॉलबैक हैं।

पदावनत:

connection:canAuthenticateAgainstProtectionSpace:
connection:didCancelAuthenticationChallenge:
connection:didReceiveAuthenticationChallenge:

इसके बजाय, आपको घोषित करने की आवश्यकता है:

connectionShouldUseCredentialStorage: - यह निर्धारित करने के लिए भेजा गया कि क्या कनेक्शन को प्रमाणित करने के लिए URL लोडर को क्रेडेंशियल स्टोरेज का उपयोग करना चाहिए।

connection:willSendRequestForAuthenticationChallenge: - प्रतिनिधि को बताता है कि कनेक्शन एक प्रमाणीकरण चुनौती के लिए अनुरोध भेजेगा।

उदाहरण के लिए, जैसे कि आप पदावनत विधियों के साथ willSendRequestForAuthenticationChallengeकर सकते हैं challenge,

// Trusting and not trusting connection to host: Self-signed certificate
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];

क्या आप इसकी जाँच कर सकते हैं: stackoverflow.com/q/56627757/1364053
nr5

3

मैंने कुछ गिस्ट कोड पोस्ट किए (किसी और के काम के आधार पर जो मैं नोट करता हूं) जो आपको स्व-निर्मित प्रमाण पत्र के खिलाफ सही तरीके से प्रमाणित करने की अनुमति देता है (और एक मुफ्त प्रमाण पत्र कैसे प्राप्त करें - कोकोनेटिक्स के नीचे टिप्पणी देखें )

मेरा कोड यहाँ github है


क्या आप इसे देख सकते हैं: stackoverflow.com/q/56627757/1364053
nr5

2

यदि आप इस समाधान में sendSynchronousRequest i काम का उपयोग करना चाहते हैं:

FailCertificateDelegate *fcd=[[FailCertificateDelegate alloc] init];

NSURLConnection *c=[[NSURLConnection alloc] initWithRequest:request delegate:fcd startImmediately:NO];
[c setDelegateQueue:[[NSOperationQueue alloc] init]];
[c start];    
NSData *d=[fcd getData];

आप इसे यहां देख सकते हैं: ऑब्जेक्टिव-सी एसएसएल सिंक्रोनस कनेक्शन


1

AFNetworking के साथ मैंने नीचे दिए गए कोड के साथ सफलतापूर्वक https वेबबेस का उपभोग किया है,

NSString *aStrServerUrl = WS_URL;

// Initialize AFHTTPRequestOperationManager...
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];

[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
manager.securityPolicy.allowInvalidCertificates = YES; 
[manager POST:aStrServerUrl parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject)
{
    successBlock(operation, responseObject);

} failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
    errorBlock(operation, error);
}];

1

आप इस कोड का उपयोग कर सकते हैं

-(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
     if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodServerTrust)
     {
         [[challenge sender] useCredential:[NSURLCredential credentialForTrust:[[challenge protectionSpace] serverTrust]] forAuthenticationChallenge:challenge];
     }
}

-connection:willSendRequestForAuthenticationChallenge:इन डिप्रेस्ड तरीकों के बजाय उपयोग करें

पदावनत:

-(BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace  
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 
-(void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.