URLSession에서 SSL 오류가 발생했을 때 Safari와 마찬가지로 액세스 할 수있게합니다.

요약


SecTrust 를 사용하여 SSL 오류를 해결합니다.

개요



Safari에서 브라우징하는 경우 사이트에 '연결이 비공개 없음'으로 표시될 수 있습니다.


이에 대해 "자세히 보기"→"이 웹사이트를 열람"으로 함으로써 사용자의 책임으로 사이트를 열람할 수 있습니다.
이것을 URLssion에서도하고 싶습니다.

Info.plist 설정



Info.plist를 App Transport Security Settings 로 설정해야 합니다.Exception Domains → 원하는 도메인 → NSExceptionAllowsInsecureHTTPLoads를 YES로 설정합니다.
이 예에서는 필드 d SL. 작은 m의 하위 도메인에서도 테스트하고 싶으므로 NSIncludesSubdomains도 YES로 둡니다.
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>badssl.com</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSIncludesSubdomains</key>
                <true/>
            </dict>
        </dict>
    </dict>

URLSession에 구현



첫째, URLession은 delegate를 붙일 수 있도록 초기화합니다.
그리고, URLSessionTaskDelegate 등, 목적의 델리게이트를 설정해, urlSession(_:didReceive:completionHandler:) 등으로 핸들링해 줍니다.

코드


class ViewController: UIViewController {
    lazy var session: URLSession = URLSession(configuration: .default, delegate: self, delegateQueue: nil)

    override func viewDidLoad() {
        super.viewDidLoad()
        let task = session.dataTask(with: URL(string: "https://revoked.badssl.com")!)
        task.resume()
    }
}

extension ViewController: URLSessionTaskDelegate {
    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
        print(#function,#line,"\(String(describing: error))")
    }

    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        //サーバー信頼チェック以外はデフォルトの挙動を行う
        guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust,
            let serverTrust = challenge.protectionSpace.serverTrust else {
                completionHandler(.performDefaultHandling, nil)
                return
        }

        // Trustを確認する
        SecTrustEvaluateAsyncWithError(serverTrust, DispatchQueue.global()) { (secTrust, trusted, error) in
            if trusted {
                completionHandler(.performDefaultHandling, nil) // 信頼できる場合デフォルトの挙動を行う
            } else {
                // エラーメッセージを表示
                let title:String
                if let error = error {
                    title = error.localizedDescription
                } else {
                    title = "接続はプライベートではありません"
                }
                DispatchQueue.main.async {
                    //アラートを表示して、ユーザーに選択を促す
                    let alert = UIAlertController(title: title,
                                                  message: "それでもサーバに接続しますか?",
                                                  preferredStyle: .alert)
                    alert.addAction(UIAlertAction(title: "接続する", style: .destructive, handler: { (alertAction) in
                        completionHandler(.useCredential, URLCredential(trust: secTrust))
                    }))

                    alert.addAction(UIAlertAction(title: "接続しない", style: .cancel, handler: { (alertAction) in
                        completionHandler(.cancelAuthenticationChallenge, nil)
                    }))

                    self.present(alert, animated: true, completion: nil)
                }
            }
        }
    }
}

코드 설명


urlSession(_:didReceive:completionHandler:) 는 기본 인증 시 등도 호출됩니다만, 이번은 서버의 신뢰에 대한 처리만이므로 NSURLAuthenticationMethodServerTrust그 이외의 경우는 특히 대처의 필요는 이번은 고려하지 않기 때문에 리턴을 합니다만, completionHandler를 반드시 호출할 필요가 있으므로, .performDefaultHandling 를 호출해 둡니다.

우선, SecTrustEvaluateAsyncWithError 에 secTrust 를 건네주어 신뢰할 수 있을지 어떨지를 콜백 받습니다.
콜백에서는 신뢰 결과가 반환되어 신뢰할 수 있다고 판단할 수 있는 경우는 그대로 .performDefaultHandling 로 처리 계속할 수 있습니다만, 신뢰할 수 없게 되었을 경우, 경고를 표시해 유저에게 판단을 받게 합니다.
CFError 의 localizedDescription 에는 에러의 원인이 포함되어 있으므로, 그것을 유저에게 제시해, 유저가 접속 가능이라고 판단했을 경우는 .useCredential 그리고 처리 계속할 수 있습니다.
사용자가 연결하지 않는다고 판단되면 .cancelAuthenticationChallenge에서 연결을 취소합니다.

액세스시 이미지



자체 인증서





만료됨





revoked





요약



잡자! SecTrust!

좋은 웹페이지 즐겨찾기