अवलोकन:
आप डिवाइस कीचेन क्लाइंट SSL प्रमाणपत्र स्थापित किया है।
सफारी.एप और मेल.एप के पास इस कीचेन तक पहुंच है जबकि आईओएस ऐप नहीं है।
कारण यह है कि हमारे द्वारा विकसित किए जाने वाले ऐप्स सैंडबॉक्स किए गए हैं और गैर-जेलब्रोकन डिवाइस में इसके बाहर कोई पहुंच अधिकार नहीं है।
सफारी के पास पहुंच के रूप में, सर्वर चुनौती के खिलाफ कनेक्ट करने और प्रमाणीकरण में कोई समस्या नहीं थी।
समाधान:
अनुप्रयोग बंडल के साथ निर्यात P12 फ़ाइल को शामिल करें और सही क्लाइंट प्रमाणपत्र सर्वर for.It वास्तव में एक समाधान नहीं है देख रहा था खोजने के लिए कहते हैं। हार्ड कोडिंग पी 12 फाइल को पकड़ने का विश्वसनीय तरीका है।
कार्यान्वयन: प्रश्न में
विधि NSURLConenction delegate
में willSendRequestForAuthenticationChallenge
है। सर्वर चुनौती को संभालने के लिए आपको NSURLAuthenticationMethodClientCertificate
चुनौती प्रकार inorder के लिए खाते की आवश्यकता है। यह वह जगह है जहां हमने एम्बेडेड पी 12 फ़ाइल से सही प्रमाण पत्र पहचान निकालने के लिए जादू लागू किया था। नीचे दिए गए कोड
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
if ([challenge previousFailureCount] > 0) {
//this will cause an authentication failure
[[challenge sender] cancelAuthenticationChallenge:challenge];
NSLog(@"Bad Username Or Password");
return;
}
//this is checking the server certificate
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
SecTrustResultType result;
//This takes the serverTrust object and checkes it against your keychain
SecTrustEvaluate(challenge.protectionSpace.serverTrust, &result);
//if we want to ignore invalid server for certificates, we just accept the server
if (kSPAllowInvalidServerCertificates) {
[challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge: challenge];
return;
} else if(result == kSecTrustResultProceed || result == kSecTrustResultConfirm || result == kSecTrustResultUnspecified) {
//When testing this against a trusted server I got kSecTrustResultUnspecified every time. But the other two match the description of a trusted server
[challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge: challenge];
return;
}
} else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate) {
//this handles authenticating the client certificate
/*
What we need to do here is get the certificate and an an identity so we can do this:
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:myCerts persistence:NSURLCredentialPersistencePermanent];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
It's easy to load the certificate using the code in -installCertificate
It's more difficult to get the identity.
We can get it from a .p12 file, but you need a passphrase:
*/
NSString *p12Path = [[BundleManager bundleForCurrentSkin] pathForResource:kP12FileName ofType:@"p12"];
NSData *p12Data = [[NSData alloc] initWithContentsOfFile:p12Path];
CFStringRef password = CFSTR("PASSWORD");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
CFArrayRef p12Items;
OSStatus result = SecPKCS12Import((CFDataRef)p12Data, optionsDictionary, &p12Items);
if(result == noErr) {
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(p12Items, 0);
SecIdentityRef identityApp =(SecIdentityRef)CFDictionaryGetValue(identityDict,kSecImportItemIdentity);
SecCertificateRef certRef;
SecIdentityCopyCertificate(identityApp, &certRef);
SecCertificateRef certArray[1] = { certRef };
CFArrayRef myCerts = CFArrayCreate(NULL, (void *)certArray, 1, NULL);
CFRelease(certRef);
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identityApp certificates:(NSArray *)myCerts persistence:NSURLCredentialPersistencePermanent];
CFRelease(myCerts);
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}
} else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodDefault || [[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodNTLM) {
// For normal authentication based on username and password. This could be NTLM or Default.
DAVCredentials *cred = _parentSession.credentials;
NSURLCredential *credential = [NSURLCredential credentialWithUser:cred.username password:cred.password persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
} else {
//If everything fails, we cancel the challenge.
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}
संदर्भ है: Ref1, Ref2, Ref3
आशा इस मदद करता है
स्रोत
2015-04-23 21:51:39
आप https के लिए स्वयं हस्ताक्षरित प्रमाणपत्र का उपयोग कर अपने वेबसाइटों और सेवाओं की सुरक्षा कर रहे हैं? या आप उपयोगकर्ता नाम और पासवर्ड का उपयोग करने के बजाय प्रमाणीकरण के साधन के रूप में प्रमाण पत्र का उपयोग करने का प्रयास कर रहे हैं? –
हम उपयोगकर्ता को प्रमाणीकृत करने के लिए प्रमाण पत्र का उपयोग करना चाहते हैं (उपयोगकर्ता नाम/पासवर्ड का उपयोग करने के बजाय)। –
आपके वेब ऐप्स NTLM या Kerberos प्रमाणीकरण के लिए उपयोग किए जाने वाले मौजूदा समाधान का क्या समाधान है? –