如何使用无效证书使用Alamofire访问本地Https?

时间:2017-05-23 23:54:16

标签: ssl swift3 alamofire

我尝试使用Alamofire连接到本地网络上的Web服务器。如果我用浏览器打开网址,它会发出ssl警告。如果我只是忽略并将异常添加到浏览器中,它肯定有效 我在这个主题上阅读了不同的帖子,包括Alamofire Github页面,但是我无法让它工作。我做错了什么?
提前谢谢!
这是测试代码:
我在类ViewController下面的代码开头声明了管理器。

let manager = SessionManager(configuration: URLSessionConfiguration.default, serverTrustPolicyManager: ServerTrustPolicyManager(policies:["10.0.1.19:4491":.disableEvaluation]))
let parameters:Parameters = ["macro":"696B38D0-AF57-4991-83DD-DFD03F1A693B", "value":""]
manager.request("https://10.0.1.19:4491/authenticatedaction.html", parameters:parameters).authenticate(user:user, password:password).response {
 response in
  debugPrint(response)
}

这是错误:

Alamofire.DefaultDataResponse(request: Optional(https://10.0.1.19:4491/authenticatedaction.html?macro=696B38D0-AF57-4991-83DD-DFD03F1A693B&value=), response: nil, data: Optional(0 bytes), error: Optional(Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “10.0.1.19†which could put your confidential information at risk." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x170134a00>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9813, NSErrorPeerCertificateChainKey=(
    "<cert(0x108066e00) s: Keyboard Maestro i: Keyboard Maestro CA>"
), NSUnderlyingError=0x170259d70 {Error Domain=kCFErrorDomainCFNetwork Code=-1202 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x170134a00>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9813, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9813, kCFStreamPropertySSLPeerCertificates=(
    "<cert(0x108066e00) s: Keyboard Maestro i: Keyboard Maestro CA>"
)}}, NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be “10.0.1.19†which could put your confidential information at risk., NSErrorFailingURLKey=https://10.0.1.19:4491/authenticatedaction.html?macro=696B38D0-AF57-4991-83DD-DFD03F1A693B&value=, NSErrorFailingURLStringKey=https://10.0.1.19:4491/authenticatedaction.html?macro=696B38D0-AF57-4991-83DD-DFD03F1A693B&value=, NSErrorClientCertificateStateKey=0}), timeline: Timeline: { "Request Start Time": 517316327.668, "Initial Response Time": 517316327.911, "Request Completed Time": 517316327.911, "Serialization Completed Time": 517316327.912, "Latency": 0.243 secs, "Request Duration": 0.243 secs, "Serialization Duration": 0.001 secs, "Total Duration": 0.244 secs }, _metrics: Optional((Task Interval) <_NSConcreteDateInterval: 0x17002b6e0> (Start Date) 2017-05-24 10:58:47 +0000 + (Duration) 0.251558 seconds = (End Date) 2017-05-24 10:58:47 +0000
(Redirect Count) 0
(Transaction Metrics) (Request) <NSURLRequest: 0x170013cd0> { URL: https://10.0.1.19:4491/authenticatedaction.html?macro=696B38D0-AF57-4991-83DD-DFD03F1A693B&value= }
(Response) (null)
(Fetch Start) 2017-05-24 10:58:47 +0000
(Domain Lookup Start) (null)
(Domain Lookup End) (null)
(Connect Start) (null)
(Secure Connection Start) (null)
(Secure Connection End) (null)
(Connect End) (null)
(Request Start) 2017-05-24 10:58:47 +0000
(Request End) 2017-05-24 10:58:47 +0000
(Response Start) 2017-05-24 10:58:47 +0000
(Response End) (null)
(Protocol Name) (null)
(Proxy Connection) NO
(Reused Connection) YES
(Fetch Type) Unknown
))

2 个答案:

答案 0 :(得分:8)

我终于解决了我的问题。有两个问题 1.我需要在函数外声明sessionManager     let manager = SessionManager(配置:URLSessionConfiguration.default,serverTrustPolicyManager:ServerTrustPolicyManager(策略:[&#34; localhost&#34;:。disableEvaluation])) 2.我在某处读到你需要包含主机的端口号,但实际上这对我来说是个问题 看起来你只需要编写&#34; localhost&#34;而不是&#34; localhost:443&#34;。
无论如何,这是将禁用所有地址评估的整个代码 您不需要将任何内容更改为Info.plist。 Xcode为您提供的默认Info.plist似乎可以正常工作 IOS 10.3.2,Xcode 8.3.2,来自Github的Alamofire Master分支(2017-05-23)

import UIKit
import Alamofire

class ViewController: UIViewController {

    open class MyServerTrustPolicyManager: ServerTrustPolicyManager {
        open override func serverTrustPolicy(forHost host: String) -> ServerTrustPolicy? {
            return ServerTrustPolicy.disableEvaluation
        }
    }

    let sessionManager = SessionManager(delegate:SessionDelegate(), serverTrustPolicyManager:MyServerTrustPolicyManager(policies: [:]))

    func connect() {
        let user = "user"
        let password = "password"
        let parameters:Parameters = ["parameter1":"value1", "parameter2":"value2"]
        sessionManager.request("https://localhost:443/index.php", parameters:parameters).authenticate(user:user, password:password).responseString {
            response in
                debugPrint(response.result.value)
            } else {
                debugPrint(response)
            }
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        connect()
    }

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

}

答案 1 :(得分:1)

在使用SessionManager时,github上的Alamofire文档中说明了这一点:

  

确保保留对新SessionManager实例的引用,   否则你的请求将被取消   sessionManager已取消分配。

首先,您可以将其作为全局变量。

示例:

let sessionManager: SessionManager = {
    let serverTrustPolicies: [String: ServerTrustPolicy] = [
        "10.0.1.19": .disableEvaluation
    ]

    return SessionManager(
        serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
    )
}()

在开发环境中使用自签名或无效证书时,可能会在NSAppTransportSecurity中添加NSAllowsArbitraryLoads并将</true>设置为Info.plist 请注意,不建议将其用于生产环境

详细说明可在Alamofire documentation

中找到
  

App Transport Security

     

随着iOS 9中的App Transport Security(ATS)的增加,它确实如此   可能是使用自定义ServerTrustPolicyManager和几个   ServerTrustPolicy对象无效。如果你不断看到   CFNetwork SSLHandshake失败(-9806)错误,你可能已经运行了   陷入这个问题。 Apple的ATS系统覆盖了整个挑战   系统,除非您在应用程序的plist中配置ATS设置   禁用足够的内容以允许您的应用评估服务器信任。

     

如果遇到这个问题(自签名的概率很高   证书),您可以通过添加以下内容解决此问题   到你的Info.plist。

<dict>
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>example.com</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSExceptionRequiresForwardSecrecy</key>
                <false/>
                <key>NSIncludesSubdomains</key>
                <true/>
                <!-- Optional: Specify minimum TLS version -->
                <key>NSTemporaryExceptionMinimumTLSVersion</key>
                <string>TLSv1.2</string>
            </dict>
        </dict>
    </dict>
</dict>
     

是否需要将NSExceptionRequiresForwardSecrecy设置为NO   取决于您的TLS连接是否使用允许的密码   套房。在某些情况下,需要将其设置为NO。该   NSExceptionAllowsInsecureHTTPLoads必须设置为YES才能   允许SessionDelegate接收质询回调。一旦   正在调用挑战回调,即ServerTrustPolicyManager   将接管服务器信任评估。你可能还需要   如果您正在尝试,请指定NSTemporaryExceptionMinimumTLSVersion   连接到仅支持小于1.2的TLS版本的主机。

     

建议始终在生产中使用有效证书   的环境中。