微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何让 Apollo 客户端 iOS 接受自签名证书

如何解决如何让 Apollo 客户端 iOS 接受自签名证书

如何让 ApolloClient 接受自签名证书?我们将它用于内部应用程序,由于认证问题,对 GraphQL 端点的调用失败。我在存储库问题中发现了 this thread,但自那次讨论以来,API 似乎发生了一些变化,目前正确的方法是我不知道的。

目前,我的集成测试下降到 .failure 分支报告证书验证问题:

        let apollo = AppConstants.current.apollo
        apollo.fetch( query: DriverStatementsIncompleteQuery( onepass: "test-user" ) ) { result in
            switch result {
            case .success( let results ):
                print( results )
                XCTAssertNil( results.errors )
                self.completedExpectation.fulfill()
            case .failure( let error ):
                XCTFail( error.localizedDescription )
                self.completedExpectation.fulfill()
            }
        }
        wait( for: [self.completedExpectation],timeout: 5 )

解决方法

Apollo iOS 团队的 Ellen Shapiro 非常友好地为我指明了正确的方向。这是我最后的结果:

public struct PromiscuousApolloClientFactory {
    /// Creates an `ApolloClient` instance that is configured to work with certificates that the
    /// OS would otherwise deem invalid,like those that are self-signed.
    /// - Parameter endpointURL: The URL of the GraphQL endpoint.
    /// - Returns: The configured `ApolloClient` instance.
    public static func make( with endpointURL: URL ) -> ApolloClient {
        let store = ApolloStore( cache: InMemoryNormalizedCache() )
        let sessionConfig = URLSessionConfiguration.default
        let client = PromiscuousURLSessionClient( sessionConfiguration: sessionConfig )
        let provider = LegacyInterceptorProvider( client: client,store: store )
        let transport = RequestChainNetworkTransport( interceptorProvider: provider,endpointURL: endpointURL )
        
        return ApolloClient( networkTransport: transport,store: store )
    }
}

private class PromiscuousURLSessionClient: URLSessionClient {
    override func urlSession( _ session: URLSession,didReceive challenge: URLAuthenticationChallenge,completionHandler: @escaping ( URLSession.AuthChallengeDisposition,URLCredential? ) -> Void ) {
        let protectionSpace = challenge.protectionSpace
        
        guard protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust,let serverTrust = protectionSpace.serverTrust else {
                completionHandler( .performDefaultHandling,nil )
                return
        }
        
        let credential = URLCredential( trust: serverTrust )
        completionHandler( .useCredential,credential )
    }
}

注意事项:这通常是一种不好的做法,因为它会短路对您有利的安全保护。如果您有使用操作系统可以验证的证书的路径,请改为执行此操作。 :)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。