nginx 와 ios 는 https 양 방향 인증 을 실현 합 니 다.
nginx 키 설정 은 다음 과 같 습 니 다.
listen 443;
server_name localhost;
ssl on;
ssl_certificate /usr/local/opt/nginx/certificates/server.cer;
ssl_certificate_key /usr/local/opt/nginx/certificates/server.key.pem;
ssl_client_certificate /usr/local/opt/nginx/certificates/ca.cer;
ssl_verify_client on;
ssl 오픈 https sslcertificate 는 서버 인증서 의 경로 입 니 다. sslcertificate_key 는 서버 의 비밀 키 경로 입 니 다.
ssl_verify_client 는 양 방향 인증 설정 (client certificate)
ssl_client_certificate 는 클 라 이언 트 인증 서 를 발급 하 는 루트 인증서 입 니 다.
왜 루트 인증서 입 니까? 많은 클 라 이언 트 인증 서 를 발급 할 수 있 기 때문에 이 루트 인증서 가 서명 한 것 이 라면 서버 는 인증 통과 로 간주 합 니 다.
설정 이 완료 되면 일반적으로 80 포트 의 http 요청 을 443 포트 로 옮 겨 야 합 니 다. 그렇지 않 으 면 사용 자 는 80 포트 를 통 해 http 방식 으로 접근 할 수 있 고 안전 보호의 의 미 를 잃 습 니 다.
클 라 이언 트 코드
인터넷 에서 ios client certificate 의 게시 물 을 많이 찾 았 습 니 다. 코드 가 완전 하지 않 거나 오래된 게시 물이 나 NSURLConnection 을 사 용 했 습 니 다. delegate method 는 모두 deprecated 되 었 습 니 다. 마지막 으로 코드 세 션 을 찾 아 고 쳤 습 니 다.
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSURL *url = [NSURL URLWithString:@"https://localhost/svc/portal/setting"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPShouldHandleCookies:NO];
[request setTimeoutInterval:30];
[request setHTTPMethod:@"GET"];
NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSString *message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", message);
}];
[task resume];
위의 코드 세 션 은 NSURLSession DataTask 로 https 요청 을 합 니 다.ssl 악수 단계 에서 아래 delegate method 를 2 회 호출 합 니 다.
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
NSString *method = challenge.protectionSpace.authenticationMethod;
NSLog(@"%@", method);
if([method isEqualToString:NSURLAuthenticationMethodServerTrust]){
NSString *host = challenge.protectionSpace.host;
NSLog(@"%@", host);
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
return;
}
NSString *thePath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"];
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
CFDataRef inPKCS12Data = (CFDataRef)CFBridgingRetain(PKCS12Data);
SecIdentityRef identity;
// p12
OSStatus result = [self extractP12Data:inPKCS12Data toIdentity:&identity];
if(result != errSecSuccess){
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
return;
}
SecCertificateRef certificate = NULL;
SecIdentityCopyCertificate (identity, &certificate);
const void *certs[] = {certificate};
CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:(NSArray*)CFBridgingRelease(certArray) persistence:NSURLCredentialPersistencePermanent];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
}
-(OSStatus) extractP12Data:(CFDataRef)inP12Data toIdentity:(SecIdentityRef*)identity {
OSStatus securityError = errSecSuccess;
CFStringRef password = CFSTR("the_password");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
securityError = SecPKCS12Import(inP12Data, options, &items);
if (securityError == 0) {
CFDictionaryRef ident = CFArrayGetValueAtIndex(items,0);
const void *tempIdentity = NULL;
tempIdentity = CFDictionaryGetValue(ident, kSecImportItemIdentity);
*identity = (SecIdentityRef)tempIdentity;
}
if (options) {
CFRelease(options);
}
return securityError;
}
위의 코드 세 션 은 복사 하거나 사용 할 수 있 으 니 도움 이 되 기 를 바 랍 니 다.이 방법 은 두 번 호출 됩 니 다. 첫 번 째 는 ios app 이 server 를 검증 하 는 단계 이 고 두 번 째 는 server 가 ios app 을 검증 하 는 단계 입 니 다. 즉, client certificate 입 니 다.관건 은 각 단계 의 검증 이 끝 난 후에 completionHandler 방법 을 호출 하 는 것 이다.인터넷 에 올 라 오 는 댓 글 대부분이...
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
이 줄 코드 는 유효 하지 않 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.