Swift 2 - Xcode 7.0 не может получить доступ к сайту HTTPS с ненадежным сертификатом SSL

Эксперты, я новичок в IOS 9/XCODE 7/Swift 2 Development Kit

Я пытаюсь создать приложение ios, которое просто направляется в веб-приложение по протоколу HTTPS. Ниже мой код до сих пор в ViewController.swift

import UIKit

class ViewController: UIViewController {

    @IBOutlet var myWebView: UIWebView!

    /**
     * Function to Display the Web Application initial URL
     */
    func loadAppURL(){
        let siteAddress = "https://domain:8443/path/to/page"
        let url = NSURL (string: siteAddress)
        let urlRequest = NSURLRequest(URL: url!)
        myWebView.loadRequest(urlRequest)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        loadAppURL()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

При создании моего приложения отображается приведенное ниже сообщение об ошибке

2015-10-01 01:05:13.879 Тестер веб-страниц [2947:31838] Ошибка HTTP-загрузки NSURLSession/NSURLConnection (kCFStreamErrorDomainSSL, -9807)

и если я попытаюсь создать свое приложение вместо "https://domain:8443/path/to/page" с " http://www.apple.com" работает нормально.

Я могу получить доступ к своему веб-приложению в Safari, и оно запрашивает принятие рисков безопасности. и я принимаю это, и я могу получить доступ к своему приложению.

Направьте меня, чтобы исправить мои проблемы, спасибо заранее.


person Navas Basheer    schedule 30.09.2015    source источник
comment
Это обман stackoverflow.com/questions/20365774/ stackoverflow.com/questions/8858674/   -  person jrc    schedule 01.10.2015
comment
@jrc Упомянутый вами вопрос не относится к ios 9, и решение также не в быстром, любая другая подсказка?   -  person Navas Basheer    schedule 02.10.2015


Ответы (5)


Наконец-то я это исправил

Xcode по умолчанию отклоняет ненадежные самозаверяющие сертификаты с серверов.

мы можем переопределить это с помощью NSURLConnection и можем взаимодействовать с самозаверяющим сервером, поскольку у нас есть возможность управлять аутентификацией с помощью дополнительных методов делегата, которые недоступны для UIWebView. Таким образом, используя connection:didReceiveAuthenticationChallenge, мы можем аутентифицироваться на самоподписанном сервере.

Ссылки документы NSURLAuthenticationChallenge, @ Вопрос Лило Лу

Я решил свою проблему, выполнив следующие шаги:
Шаг 1: Определил метод NSURLConnection в viewDidLoad() моего viewController.swift следующим образом

 override func viewDidLoad() {
    super.viewDidLoad()

    let siteAddress = "https://domain:8443/path/to/page"
    let url = NSURL (string: siteAddress)
    let urlRequest = NSURLRequest(URL: url!)
    let urlConnection:NSURLConnection = NSURLConnection(request: request, delegate: self)!
    myWebView.loadRequest(urlRequest)
 }

Шаг 2: используются методы делегата NSURLConnection

    func connection(connection: NSURLConnection, canAuthenticateAgainstProtectionSpace protectionSpace: NSURLProtectionSpace) -> Bool{
        print("canAuthenticateAgainstProtectionSpace method Returning True")
        return true
    }


    func connection(connection: NSURLConnection, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge){

        print("did autherntcationchallenge = \(challenge.protectionSpace.authenticationMethod)")

        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust  {
            print("send credential Server Trust")
            let credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!)
            challenge.sender!.useCredential(credential, forAuthenticationChallenge: challenge)

        }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic{
            print("send credential HTTP Basic")
            let defaultCredentials: NSURLCredential = NSURLCredential(user: "username", password: "password", persistence:NSURLCredentialPersistence.ForSession)
            challenge.sender!.useCredential(defaultCredentials, forAuthenticationChallenge: challenge)

        }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM{
            print("send credential NTLM")

        } else{
            challenge.sender!.performDefaultHandlingForAuthenticationChallenge!(challenge)
      }
}

и это сработало !!

person Navas Basheer    schedule 02.10.2015
comment
Я проголосовал за ваш ответ, потому что он был хорош, но вам действительно следует подумать о том, чтобы прекратить использовать принудительную распаковку. - person Lucas van Dongen; 20.11.2015
comment
и используйте переключатель вместо блоков if else. - person Lucas van Dongen; 20.11.2015
comment
Пробовал это, у меня не сработало. Вот код, который я использовал: pastebin.com/pd2HFWfy Я все еще получаю NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813) - person Gabriel Sanmartin; 08.03.2016
comment
Удалось ли вам успешно загрузить свое приложение в магазин? - person bhakti123; 03.09.2017
comment
@ bhakti123 Я не пытался загружать в магазин приложений. Я попробовал это с моего телефона локально, и это сработало. - person Navas Basheer; 06.09.2017

Вы можете добавить следующее в свой plist

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

введите здесь описание изображения

person Mika    schedule 30.09.2015
comment
Я добавил код в Info.plist, без изменений в ошибке, получая ту же ошибку, что и раньше - person Navas Basheer; 01.10.2015
comment
Вы убедились, что это логическое значение в словаре? Должно выглядеть так, как я только что вставил - person Mika; 01.10.2015
comment
Да, это то же самое, что вы показали в моем Xcode, я попробую решение, упомянутое здесь stackoverflow.com/questions/20365774/ - person Navas Basheer; 01.10.2015

В Свифт 3.

Шаг 1. Добавьте NSURLConnectionDelegate в свой контроллер представления, чтобы перезаписать методы.

class ViewController: UIViewController, NSURLConnectionDelegate {

Шаг 2. Переопределить viewDidLoad

override func viewDidLoad() {
        super.viewDidLoad()

        let siteAddress = "https://mysiteaddress"
        let url = URL(string: siteAddress)
        let urlRequest = URLRequest(url: url!)
        let urlConnection:NSURLConnection = NSURLConnection(request: urlRequest, delegate: self)!
        webView.loadRequest(urlRequest)
    }

Шаг 3 Перезапишите canAuthenticateAgainstProtectionSpace и didReceive challenge

func connection(_ connection: NSURLConnection, canAuthenticateAgainstProtectionSpace protectionSpace: URLProtectionSpace) -> Bool {
    print("\ncanAuthenticateAgainstProtectionSpace method Returning True\n")
    return true
}

func connection(_ connection: NSURLConnection, didReceive challenge: URLAuthenticationChallenge) {
    print("did autherntcationchallenge = \(challenge.protectionSpace.authenticationMethod)")

    if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust  {
        print("\nsend credential Server Trust\n")
        let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
        challenge.sender!.use(credential, for: challenge)

    }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic{
        print("send credential HTTP Basic")
        let defaultCredentials: URLCredential = URLCredential(user: "user", password: "password", persistence:URLCredential.Persistence.forSession)
        challenge.sender!.use(defaultCredentials, for: challenge)

    }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM{
        print("\nsend credential NTLM\n")

    } else{
        challenge.sender!.performDefaultHandling!(for: challenge)
    }

}

Спасибо Навасу Баширу за оригинальное решение! Сэкономил мне кучу времени

person plgelso    schedule 22.06.2017

1- Создайте категорию «NSURLRequestCategory» -> после импорта этой категории в ваш файл моста, созданный xcode (не забудьте разрешить xCode создать его, если вы этого не сделали), и поместите этот код:

    @implementation NSURLRequest (NSURLRequestCategory)

+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString *)host
{
    return YES;
}
@end

Создайте свой запрос на загрузку UIWebView как обычно:

webView.delegate = self
let myURL = URL(string: Constants.URL_DOMAINE)
let request = URLRequest(url: myURL!)
webView.loadRequest(request)

Наслаждайся :D

person Badre    schedule 07.11.2016

отредактируйте Info.plist, добавьте:

  1. Настройки безопасности транспорта приложений
  2. Разрешить произвольные загрузки, значение ДА

у меня работает, XCode 7.3

person kun yu    schedule 04.05.2016