현재 Android와 iOS를 동시에 개발하고 있습니다.
기존에는 TCP 통신으로만 진행하고 있었는데, HTTPS 통신이 필요하다하여 통신 기능을 개발과정에서 있었던 내용을 기록하기 위해서 적어봅니다.
Android에서 Https 통신을 하기 위해 유용하면서도 대중적으로 많이 사용하는 Retrofit를 사용하여 후딱 개발할 수 있었습니다.
그러나, iOS는 익숙하지 않아 가장 많이 사용되는 HTTP 네트워킹 라이브러리인 Alamofire을 사용하였습니다. 사용하는 와중에 삽질했던걸 기록합니다.
이제 라이브러리 설치 부터 진행하겠습니다.
1. podfile 에 라이브러리 적용
pod 'Alamofire', '~> 5.4'
- 최신을 좋아해서 최신버전으로 적용하였습니다.
- " pod install " 라이브러리 설치!!!
- 커맨드⌘ + B 를 눌러서 한번 빌드 !!!
- 참고 : Alamofire 사용법
2. HTTPS 통신 테스트 코드
import Alamofire
extension Session {
func setConnectServer(){
let url = "https://접속주소/v1/connect/information"
AF.request(url).responseJSON{ (data) in
print(data)
}
}
}
- 단순 예제 코드 보고, 접속 시도했습니다.
- 바로...역시나... 한번에 되지 않았습니다... 예제는 왜 그냥 단순히 저렇게만 하면 된다고들 나오는건지..
- 문제는 HTTPS 도메인을 연결하기 위해선 SSL 인증이 필요한데 이를 제대로 설정하지 않아.. 에러가 따악!!
2021-07-13 17:01:31.522498+0900 Aegis[1702:1690397] TIC SSL Trust Error [1:0x2821d1bc0]: 3:0 2021-07-13 17:01:31.550299+0900 Aegis[1702:1690397] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813) 2021-07-13 17:01:31.550450+0900 Aegis[1702:1690397] Task <1671040B-46AE-4E28-B1C5-B358238FDF6C>.<1> HTTP load failed (error code: -1202 [3:-9813]) 2021-07-13 17:01:31.552344+0900 Aegis[1702:1690397] Task <1671040B-46AE-4E28-B1C5-B358238FDF6C>.<1> finished with error - code: -1202 2021-07-13 17:01:31.570777+0900 Aegis[1702:1690392] Task <1671040B-46AE-4E28-B1C5-B358238FDF6C>.<1> load failed with error Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “IPaddress” which could put your confidential information at risk." UserInfo={NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, NSErrorPeerCertificateChainKey=( "<cert(0x103868e00) s: Rearch i: Rearch>" ), NSErrorClientCertificateStateKey=0, NSErrorFailingURLKey=https://IPAddress/v1/connect/information, NSErrorFailingURLStringKey=https://IPAddress/v1/connect/information, NSUnderlyingError=0x281abbb10 {Error Domain=kCFErrorDomainCFNetwork Code=-1202 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x2826dccf0>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9813, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9813, kCFStreamPropertySSLPeerCertificates=( "<cert(0x103868e00) s: Rearch i: Rearch>" )}}, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalDataTask <1671040B-46AE-4E28-B1C5-B358238FDF6C>.<1>" ), _kCFStreamErrorCodeKey=-9813, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <1671040B-46AE-4E28-B1C5-B358238FDF6C>.<1>, NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x2826dccf0>, NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be “IPAddress” which could put your confidential information at risk.} [-1202] failure(Alamofire.AFError.sessionTaskFailed(error: Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “IPAddress” which could put your confidential information at risk." UserInfo={NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, NSErrorPeerCertificateChainKey=( "<cert(0x103868e00) s: Rearch i: Rearch>" ), NSErrorClientCertificateStateKey=0, NSErrorFailingURLKey=https://IPAddress/v1/connect/information, NSErrorFailingURLStringKey=https://IPAddress/v1/connect/information, NSUnderlyingError=0x281abbb10 {Error Domain=kCFErrorDomainCFNetwork Code=-1202 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x2826dccf0>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9813, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9813, kCFStreamPropertySSLPeerCertificates=( "<cert(0x103868e00) s: Rearch i: Rearch>" )}}, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalDataTask <1671040B-46AE-4E28-B1C5-B358238FDF6C>.<1>" ), _kCFStreamErrorCodeKey=-9813, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <1671040B-46AE-4E28-B1C5-B358238FDF6C>.<1>, NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x2826dccf0>, NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be “IPAddress which could put your confidential information at risk.})) |
3. 1차 이슈 해결
- ATS를 제외시킬 도메인을 Info.plist에 기재하여 통신
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>제외 시키고자 하는 URL</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
- Info.plist 수정 할때 참고
- 그래도... 문제 해결되지 않음...
4. 2차 이슈 해결
- Alamofire 에서 SessionManager에서 제외할 IP 주소를 추가
< Alamofire Version 5.x >
let sessionManager: Session = {
let serverTrustPolices = ServerTrustManager(evaluators: ["제외 시키고자 하는 URL": DisabledTrustEvaluator()])
let configuration = URLSessionConfiguration.af.default
configuration.timeoutIntervalForRequest = 30
return Session(configuration: configuration, serverTrustManager: serverTrustPolices)
}()
let url = "https://접속주소/v1/connect/information"
sessionManager.request(url).responseJSON { (data) in
print(data)
}
< Alamofire Version 4.x >
private static var Manager: Alamofire.SessionManager = {
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"제외 시키고자 하는 URL": .disableEvaluation
]
let manager = Alamofire.SessionManager(
configuration: URLSessionConfiguration.default,
delegate: SessionDelegate(),
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
return manager
}()
request = Manager.request(URL)
.responseJSON { response in
}
출처: https://gogorchg.tistory.com/entry/iOS-Alamofire [항상 초심으로]
- 결과는.. 이전과 다른 에러 발생.. 뭔가 되는것 처럼 보임...
[ERROR] Alamofire ssl wrong: sessionDeinitialized |
5. 3차 이슈 해결
- " Alamofire ssl wrong : sessionDeinitialized " 에러 원인
- 만들어진 Session 인스턴스를 활성화 상태로 유지 필요
-> 그렇치 않으면 즉시 초기화 해제되고, 요청이 취소되어 에러 발생
- 싱글톤 또는 기타 참조 스토리지 패턴으로 수행 필요
* 최종 코드 *
public static let sessionManager: Session = {
let serverTrustPolices = ServerTrustManager(evaluators: ["제외 시키고자 하는 URL": DisabledTrustEvaluator()])
let configuration = URLSessionConfiguration.af.default
configuration.timeoutIntervalForRequest = 30
return Session(configuration: configuration, serverTrustManager: serverTrustPolices)
}()
fun onConnectServer(){
let url = "https://접속주소/v1/connect/information"
sessionManager.request(url,
method: .get,
encoding: URLEncoding.httpBody,
headers: [:]).responseJSON { (data) in
print("Country Server Result : \(data)")
}
}
- 가장 단순하게 static으로 진행하였습니다.
- 다른 방법도 있으니, 조금이나마 도움이 되었으면 좋겠습니다.
'iOS' 카테고리의 다른 글
[ iOS ] Target Network Extension 추가 후 "No such Module" 이슈 처리 (3) | 2021.07.30 |
---|---|
[Basic] UIKit 이란? (0) | 2021.07.26 |
[Basic] Foundation 이란? (0) | 2021.07.26 |