Swift 2 - Xcode 7.0 无法使用不受信任的 SSL 证书访问 HTTPS 站点
Swift 2 - Xcode 7.0 Cannot Access HTTPS site with unstrusted SSL Certificate
专家们,我是 IOS 9 / XCODE 7 / Swift 2 开发套件的初学者
我正在尝试创建一个 ios 应用程序,它仅通过 HTTPS 协议路由到 Web 应用程序。以下是我目前在 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 Web Page Tester[2947:31838]
NSURLSession/NSURLConnection HTTP load failed
(kCFStreamErrorDomainSSL, -9807)
如果我尝试构建我的应用程序而不是“https://domain:8443/path/to/page" with "http://www.apple.com”,它工作正常。
我可以在 Safari 中访问我的 Web 应用程序,它要求接受安全风险。我接受它,我可以访问我的应用程序。
指导我解决我的问题,在此先感谢。
您可以将以下内容添加到您的 plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
我终于修好了
Xcode 默认情况下将拒绝来自服务器的不受信任的自签名证书。
我们可以使用 NSURLConnection
覆盖它并且可以与自签名服务器通信,因为我们能够通过 UIWebView 无法使用的其他委托方法来控制身份验证。所以使用 connection:didReceiveAuthenticationChallenge
我们可以对自签名服务器进行身份验证。
参考资料
NSURLAuthenticationChallenge Docs , @Lilo Lu's
我通过以下步骤解决了我的问题
第 1 步: 在我的 viewController.swift 的 viewDidLoad()
方法中定义了一个 NSURLConnection
如下
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)
}
}
成功了!!
编辑Info.plist,添加:
- 应用传输安全设置
- 允许任意加载,值为 YES
对我有用,XCode 7.3
1- 创建类别 "NSURLRequestCategory" -> 将此类别导入由 xcode 创建的桥接文件后(如果您还没有,请不要忘记让 xCode 创建一个' t) 并输入此代码:
@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
在Swift3.
第 1 步。将 NSURLConnectionDelegate
添加到您的 viewcontroller,以覆盖方法。
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)
}
}
感谢 Navas Basheer 提供原始解决方案!为我节省了大量时间
专家们,我是 IOS 9 / XCODE 7 / Swift 2 开发套件的初学者
我正在尝试创建一个 ios 应用程序,它仅通过 HTTPS 协议路由到 Web 应用程序。以下是我目前在 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 Web Page Tester[2947:31838] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9807)
如果我尝试构建我的应用程序而不是“https://domain:8443/path/to/page" with "http://www.apple.com”,它工作正常。
我可以在 Safari 中访问我的 Web 应用程序,它要求接受安全风险。我接受它,我可以访问我的应用程序。
指导我解决我的问题,在此先感谢。
您可以将以下内容添加到您的 plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
我终于修好了
Xcode 默认情况下将拒绝来自服务器的不受信任的自签名证书。
我们可以使用 NSURLConnection
覆盖它并且可以与自签名服务器通信,因为我们能够通过 UIWebView 无法使用的其他委托方法来控制身份验证。所以使用 connection:didReceiveAuthenticationChallenge
我们可以对自签名服务器进行身份验证。
参考资料
NSURLAuthenticationChallenge Docs , @Lilo Lu's
我通过以下步骤解决了我的问题
第 1 步: 在我的 viewController.swift 的 viewDidLoad()
方法中定义了一个 NSURLConnection
如下
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)
}
}
成功了!!
编辑Info.plist,添加:
- 应用传输安全设置
- 允许任意加载,值为 YES
对我有用,XCode 7.3
1- 创建类别 "NSURLRequestCategory" -> 将此类别导入由 xcode 创建的桥接文件后(如果您还没有,请不要忘记让 xCode 创建一个' t) 并输入此代码:
@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
在Swift3.
第 1 步。将 NSURLConnectionDelegate
添加到您的 viewcontroller,以覆盖方法。
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)
}
}
感谢 Navas Basheer 提供原始解决方案!为我节省了大量时间