在 iPhone 应用程序中,我想从经过身份验证的 HTTPS 图像数据发布中收集 JSON 输出。也就是说,相当于:
curl -u "username":"password" \
-X POST \
-F "file=@image.png" \
"https://server.com/blah?param=value"
这个命令已经过验证,可以使用真实的 URL,而不是这个为了提问而给出的虚拟 URL。服务器需要基本身份验证。
遵循 Alamofire readme 中的“上传 MultipartFormData”示例和 this stackoverflow example ,我第一次尝试像这样使用 Alamofire:
// 'username' and 'password' are string literals. 'img' is a valid UIImage.
let url = NSURL("https://server.com/blah?param=value")
let dat = UIImagePNGRepresentation(img)
let credentialData = "\(username):\(password)".dataUsingEncoding(NSUTF8StringEncoding)!
let base64Credentials = credentialData.base64EncodedStringWithOptions([])
let headers = ["Authorization": "Basic \(base64Credentials)"]
Alamofire.upload(
Alamofire.Method.POST,
url!,
headers: headers,
multipartFormData: { multipartFormData in
multipartFormData.appendBodyPart(data:dat!, name:"file")
},
encodingCompletion: { encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
upload.responseString { response in
//JSON = response.result.value! as String
debugPrint(response)
}
case .Failure(let encodingError):
print(encodingError)
}
})
同样,此代码片段使用虚拟 url,但我使用真实 url 运行代码。这会导致 SSL 错误:
2015-12-31 05:28:34.733 AutoAlbum[13518:249313] _BSMachError: (os/kern) invalid capability (20)
2015-12-31 05:28:34.733 AutoAlbum[13518:249682] _BSMachError: (os/kern) invalid name (15)
2015-12-31 05:28:35.413 AutoAlbum[13518:249708] CFNetwork SSLHandshake failed (-9824)
2015-12-31 05:28:35.415 AutoAlbum[13518:249708] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)
[Request]: <NSMutableURLRequest: 0x7fdeda835040> { URL: https://server.com/blah?param=value }
[Response]: nil
[Data]: 0 bytes
[Result]: FAILURE: Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={_kCFStreamErrorCodeKey=-9824, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSUnderlyingError=0x7fdeda84bd90 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9824, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9824}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://server.com/blah?param=value, NSErrorFailingURLStringKey=https://server.com/blah?param=value, _kCFStreamErrorDomainKey=3}
当有网络连接时,此错误发生在 xcode 的 iPhone 5s 模拟器上。
我的第二种方法是:
let PasswordString = "username:password"
let PasswordData = PasswordString.dataUsingEncoding(NSUTF8StringEncoding)
let base64EncodedCredential = PasswordData!.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
let urlPath: String = "https://server.com/blah?param=value"
let url: NSURL = NSURL(string: urlPath)!
var request: NSMutableURLRequest = NSMutableURLRequest(URL: url)
request.setValue("Basic \(base64EncodedCredential)", forHTTPHeaderField: "Authorization")
request.HTTPMethod = "POST"
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let authString = "Basic \(base64EncodedCredential)"
config.HTTPAdditionalHeaders = ["Authorization" : authString]
let session = NSURLSession(configuration: config)
let img:UIImage = getAsset(asset, size: PHImageManagerMaximumSize)
let dat = String(UIImagePNGRepresentation(img))
let qstr = "file=\(dat)"
request.HTTPBody = qstr.dataUsingEncoding(NSUTF8StringEncoding)
var dataString = ""
session.dataTaskWithRequest(request) {
(let data, let response, let error) in
if let httpResponse = response as? NSHTTPURLResponse {
dataString = String(data: data!, encoding: NSUTF8StringEncoding)!
print(dataString)
}
else {
print(error)
}
}.resume()
这导致了同样的 ssl 错误:
AutoAlbum[15614:316266] CFNetwork SSLHandshake failed (-9824)
2015-12-31 15:47:51.142 AutoAlbum[15614:316266] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)
Optional(Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made."
正在关注 this example ,我尝试将最低 tls 版本设置为 1.0,如下所示:
但遇到了同样的错误。
任何人都可以在我的代码中发现问题,或者任何人是否可以就如何使用 iOS 技术来执行 curl
命令的操作提出建议?
最佳答案
这与身份验证无关,iOS 由于某些原因无法与服务器建立 https 连接(Code -1200 means“由于无法更具体地表达的原因而尝试建立安全连接失败时返回”)。
Curl 可以执行此请求,因为它不像 ATS 那样执行严格的检查,因此您应该正确配置它,并且您尝试这样做。 但是您在 ATS 配置中有一些错误,这就是请求仍然失败的原因。
NSAllowsArbitraryLoads
应该是 bool 类型,而不是字符串NSExceptionMinimumTLSVersion
应该嵌入到带有域名的字典中(仔细看你的例子,当你应该将yourserver.com
替换为实际域名时,你错过了部分). This is a link关于如何为 ATS 正确配置异常的官方文档,它提供了有关其工作原理的更多详细信息。此外,为特定域指定
NSAllowsArbitraryLoads
和NSExceptionMinimumTLSVersion
是多余的,因为NSAllowsArbitraryLoads
将覆盖此设置。
关于swift - 如何在 Swift 中制作经过身份验证的 HTTPS 帖子?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34545172/