Alamofire 4.0的证书无效问题 [英] Certificate Invalid Issue with Alamofire 4.0

查看:230
本文介绍了Alamofire 4.0的证书无效问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过https为iOS应用使用Web服务。 Web服务器使用自签名证书。

I am trying to consume web services for my iOS app over https. The web server uses a self signed certificate.

使用Web服务时,出现错误证书无效。

When consuming the web service, I get the error "certificate is Invalid".


失败:错误域= NSURLErrorDomain代码= -1202此服务器的证书无效。您可能正在连接到假装为门户的服务器,这可能会使您的机密信息有风险。

FAILURE: Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be "portal" which could put your confidential information at risk."

我知道最佳实践是在服务器端修复此问题,以启用受信任的根CA。但是由于这是一个临时的开发环境,因此我们使用的是自签名证书。
因为这是ATS问题,所以我在如下的info.plist中编辑了ATS。

I know the best practise is to fix this at the server side to enable a trusted root CA. But as this is a temporary development environment, we are using a self signed certificate. Since this is ATS issue, I have edited ATS in my info.plist as below.

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>devportal</key>
        <dict>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.2</string>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
</dict>
</plist>

由于NSException域不适用于IP和端口号,因此我在我的Web服务器IP的etc / hosts文件,并像 https:// devportal:8443 / rest / login一样使用它a>而不是将其作为 https://192.22.xx.xxx:8443/rest/login

As the NSException domains doesn’t work with IP and port number, I have created a host entry in my etc/hosts file for the web server IP and consuming it like https://devportal:8443/rest/login instead of consuming it as https://192.22.xx.xxx:8443/rest/login

我遵循了有关服务器信任策略的alamofire文档,对ATS进行了编辑,以允许使用例外域,但对我而言没有任何解决方法。我在这个问题上花了3天多的时间。我想念什么吗?有人遇到过类似的问题吗?有什么解决办法吗?预先感谢

I have followed alamofire documentation on server trust policies, edited ATS to allow exception domains but nothing worked out for me. I have spent over 3 days on this issue. Am I missing something? Does anybody faced a similar issue? Is there any solution for this? Thanks in advance

我正在使用almofire 4.0,Xcode 8.0。下面是我的代码。

I am using almofire 4.0, Xcode 8.0. Below is my code.

class LoginService{
     private static var Manager: Alamofire.SessionManager = {

          let pathToCert = Bundle.main.path(forResource: "192.22.xx.xxx", ofType: "crt") // Downloaded this certificate and have added to my bundle
          let localCertificate:NSData = NSData(contentsOfFile: pathToCert!)!

          // Create the server trust policies
          let serverTrustPolicies: [String: ServerTrustPolicy] = [
               "192.22.xx.xxx": .pinCertificates(
                    certificates: [SecCertificateCreateWithData(nil, localCertificate)!],
                    validateCertificateChain: true,
                    validateHost: true
               ),

               "devportal:8443": .disableEvaluation
          ]

          // Create custom manager
          let configuration = URLSessionConfiguration.default
          configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
          let manager = Alamofire.SessionManager(
               configuration: URLSessionConfiguration.default,
               serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
          )

          return manager
     }()



     /**
      Calls the Login Web Service to authenticate the user
      */
     public func login(username:String, password: String){

          let parameters = [
               "username": "TEST",
               "password": "PASSWORD",
                  ]
          let header: HTTPHeaders = ["Accept": "application/json"]
          LoginService.Manager.request("https://devportal:8443/rest/login", method: .post, parameters: parameters, encoding: JSONEncoding(options: []),headers :header).responseJSON { response in
               debugPrint(response)

               if let json = response.result.value {
                    print("JSON: \(json)")
               }
          }



     }
}


推荐答案

我修改了我的代码,如下所示,它可以正常工作。我提到了 Swift:如何使用服务器SSL证书提出Https请求,以解决此问题。

I modified my code like below and it worked. I referred Swift: How to Make Https Request Using Server SSL Certificate for fixing this issue.

       class LoginService{
             private static var Manager: Alamofire.SessionManager = {

                  // Create the server trust policies
                  let serverTrustPolicies: [String: ServerTrustPolicy] = [

                       "devportal:8443": .disableEvaluation
                  ]

                  // Create custom manager
                  let configuration = URLSessionConfiguration.default
                  configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
                  let manager = Alamofire.SessionManager(
                       configuration: URLSessionConfiguration.default,
                       serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
                  )

                  return manager
             }()



             /**
              Calls the Login Web Service to authenticate the user
              */
             public func login(username:String, password: String){

    // Handle Authentication challenge

          let delegate: Alamofire.SessionDelegate = LoginService.Manager.delegate
         delegate.sessionDidReceiveChallenge = { session, challenge in
              var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling
              var credential: URLCredential?
              if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
                   disposition = URLSession.AuthChallengeDisposition.useCredential
                   credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
              } else {
                   if challenge.previousFailureCount > 0 {
                        disposition = .cancelAuthenticationChallenge
                   } else {
                        credential = LoginService.Manager.session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace)
                        if credential != nil {
                             disposition = .useCredential
                        }
                   }
              }
              return (disposition, credential)
         }

//Web service Request    
                  let parameters = [
                       "username": "TEST",
                       "password": "PASSWORD",
                          ]
                  let header: HTTPHeaders = ["Accept": "application/json"]
                  LoginService.Manager.request("https://devportal:8443/rest/login", method: .post, parameters: parameters, encoding: JSONEncoding(options: []),headers :header).responseJSON { response in
                       debugPrint(response)

                       if let json = response.result.value {
                            print("JSON: \(json)")
                       }
                  }



             }
        }

您还应该按以下方式配置plist

You should also configure your plist as below

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>devportal</key>
        <dict>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.2</string>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
</dict>
</plist>




请勿在NSExceptiondomain中输入IP或端口号。
不会起作用。如果您尝试使用IP地址连接到Web服务器,则
通过在Mac的etc / hosts
文件中添加主机条目,然后在NSExceptionDomains中使用域名,将$ IP地址映射到域

Do not enter IP or port numbers in your NSExceptiondomains. It won't work. If you are trying to connect to a web server with IP address, map the IP address to a domain by adding a host entry in etc/hosts file in your mac and then use the domain name in NSExceptionDomains

重要提示::请勿在生产环境中使用此代码,因为这会绕过身份验证挑战,使您的用户
信息处于危险之中。 / p>

IMPORTANT: Do not use this code in production as this puts your users information at risk, by bypassing auth challenge.

这篇关于Alamofire 4.0的证书无效问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆