原文:Charles Proxy Tutorial for iOS
作者:Aaron Douglas
译者:kmyhy
有时不得不承认——我们曾经写过一些代码,它们不正确,但我们又无法调试。更麻烦的是,你需要通过网络和其它系统通讯的时候。
幸运的是,Charles 代理能够让网络调试变得简单。
Charles 代理位于 App 和网络之间。所有的网络请求、响应都必须经过 Charlse 代理,因此你就能够观察和修改所经过的数据,以测试 App 的行为。
在这篇 Charles 代理教程中,你将通过亲自动手操作来学习它(以及更多)。
首先需要下载最新版本的 Charles Proxy(写到这里的时候是 v4.1.1)。双击 dmg 文件,将 Charles 图标拖进应用程序文件夹以安装它。
Charles Proxy 不免费,但你可以有 30 天的试用期。Charles 在试用版模式下每次只能运行 30 分钟,因此你在本教程学习过程中你可能需要重启它。
注意:Charles 是一个 Java App,支持 macOS、Windows 和 Linux。这篇 Charles Proxy 教程只针对 macOS,可能在其它平台下稍有不同。
点开 Charles,它会询问是否允许它配置你的网络设置。
点击 Grant Privileges 然后输入你的密码。Charles 启动后会开始记录网络事件。你可以看到左边的面板中会加入一些网络事件。
注意:如果你无法看到事件,可能是你没有授权或者开启了另外一个代理。如果需要帮助,请查看 Charles 的 FAQ 页。
用户界面非常简单,哪怕你没用过它也能够看懂。有许多内容都被隐藏到按钮和菜单下面,但是在工具栏中有几个东西是你必须认识的:
现在,点击红色的“记录/暂停”按钮,停止记录。
左面板可以在 Structure 和 Sequence 视图之间切换。当选择 Structure 视图时,所有的活动是以网站地址的形式进行分组的。你可以通过点击网址旁边的箭头查看每个请求。
当选择 Sequence 视图时,你可以按时间顺序查看连续的事件列表。当调试你的 app 时,大部分时候你都会停留在这个界面。
默认,Charles 将请求/响应合并在一个窗口中显示。但我建议你将它们分成两个单独事件进行显示,这样会更清楚。
点击 Charles\Preferences ,选择 Viewers 标签,反选 Combine request and response ,然后 OK。为了使设置生效,你需要重启 Charles。
尝试操作一下用户界面,观察各种事件。你会注意到一个特别的地方:对于 HTTPS 事件,你无法查看细节。
SSL/TLS 用于对敏感的请求响应信息进行加密。你可能想,Charles 对 HTTPS 事件就没招了吗?No!Charles 有一种特殊的方法,能够绕开加密规则,后面我们会介绍。
你可能好奇,“Charlse 是如何做到这一切的呢?”
Charles 是一个代理服务器,这意味着它可以插入到 App 和计算机的网络连接之间。Charles 会自动配置你的网络设置,将你的网络设置成所有的通信都必须经过它转发。这样就使得 Charles 能够监听所有的从计算机发出和收到的网络事件。
代理服务器的威力十分强大,但很容易被滥用。因此 SSL 就变得十分重要了:它会对数据进行加密,防止代理服务器和其它中间件窃取敏感信息。
但是在我们的例子里,我们必须用 Charles 来嗅探我们的 SSL 信息,以便我们能够进行调试。
SSL/TLS 信息通过受信任的第三方即所谓的“证书发行机构”来创建证书。
Charles 也可以生成它自己的自签名证书,你可以将它们安装到 Mac 和 iOS 设备中并用于 SSL/TLS 加密。因为这个证书并不是由受信任的第三方证书发行机构发出的,因此你必须手动告诉设备去信任它。当证书被安装并被信任之后,Charles 就能看懂 SSL 事件了。
因为黑客们也是使用中间件来嗅探网络通讯的,即“中间人攻击”。一般情况下,你不应该信任任何随机的证书,否则你的网络将不再安全。
有几种情况会导致 Charles 的“中间人策略”不生效。例如,有的 App 会使用“SSL pinning”来强化安全。SSL pinning 表示 App 中会有一份 SSL 证书的公钥,在开始通讯之前,App 会用这个证书来检验网络连接。Charles 的 key 肯定是和公钥不匹配的,App 会拒绝本次通讯。
除了记录事件,Charles 还可以实时修改数据,然后记录下来以便查看,甚至可以故意模拟错误的网络连接。Charles 确实很强大!
要让 Charles 作为你网络中的任意计算机和设备(包括 iOS 设备)的代理,也很简单。
首先,在 Charles 中点击 Proxy(下拉菜单)\macOS Proxy ,取消勾选以关闭 macOS Proxy。这样,你就只能查看 iOS 设备上的流量了。
然后,点击 Proxy\Proxy Settings,记下 Proxies 一栏中的端口号,默认是 8888。
然后点击 Help\Local IP Address ,记下计算机的 IP 地址。
拿起你的 iOS 设备,打开设置程序,点击 Wi-Fi,检查是否和计算机处于同一网络。然后点击这个 WiFi 连接旁边的 ⓘ 按钮。 找到 HTTP Proxy ,点击 Manual。
在 Server 中输入 Mac 的 IP 地址,Port 一栏输入 Charles HTTP 代理端口号。点击返回按钮或者按下 Home 键,修改会自动保存。
如果之前已经停止了 Charles 的记录,则点击“记录/暂停”按钮,开始再次记录。
在 Mac 的 Charles 中,会弹出一个警告,问你是否允许 iOS 设备进行连接。请点 Allow 允许。如果你没有立即看到这个提示也没关系,稍等一两分钟,它就会出来了。
现在你可以在 Charles 中看到来自于设备的网络活动了!
然后,在 iOS 设备,打开 Safari,浏览网址 http://www.charlesproxy.com/getssl。
这会弹出一个窗口,问你是否安装一个 Profile 或证书。在详情部分,你应当看到这是一个自签名的 Charles 证书。点击 Install,然后再次点 Install。最终,点 Done。
苹果其实想确保你是想安装这个证书的!再次强调,不要安装任何随机的证书,否则你的网络将不再安全!在本教程的最后,你需要删除这个证书。
如果你像其他开发者一样,你会好奇事情到底是怎么发生的。
Charles 有几个工具能满足你的这份好奇心,它们能够查看任何 App 的网络通信——哪怕不是你自己的 App。
打开设备上的 App Store,搜索并安装 Weather Underground。这个免费 App 在大部分国家都是有效的。如果不行,或者你想看看别的 App,请随意下载其它 App。
在下载这个 App 时,你会在 Charles 中看到有海量活动显示。App Store 真的很话痨!
当 App 安装完,打开这个 App,然后点击 Charles 的“扫帚”图标,清除最近活动。
在这个 App 中,输入 90210 作为邮编,输入 Beverley Hills 作为你的地址。如果你使用其它地址作为当前地址,则 App 抓取数据的 URL 也会改变,因为你的地址不一样了啊。这样在本教程后面的内容很可能就对不上了。
在 Structure 视图中有大量的站点被列出来!这是来自于 iOS 设备上的全部活动,而不仅仅是来自 Weather Underground App 的。
切换到 Sequence 视图,然后在过滤器中输入 wund,以便只显示 Weather Underground 的活动。
你现在只看到几个对 api.wunderground.com 的请求了。点击其中一个。
在 Overview 栏中,显示的是请求的细节,但不是全部。无论请求还是响应都看不到太多内容。Overview 会告诉你这是为什么:“SSL 代理没有在这个主机上开启:请在 Proxy Settings, SSL locations 中启用它。” 。接下来我们就启用它。
点击 Proxy\SSL Proxying Settings,点击 Add; 在 Host 中输入 api.wunderground.com for the Host,Port 中留空,然后按 OK 关闭窗口。
回到 Wunderground app,向下拉,刷新数据。如果 app 没有刷新数据,你需要关闭进程,然后重新打开。
哇!没有加密过的请求!找一条 URL 中含有 forecast10day 字样的请求。这个请求包含了用于渲染天气界面的内容。
让我们来玩点有趣的事情,在 app 获得数据之前修改数据。你可以让 app 停止或者更搞笑一点吗?
在 Sequence 列表中右键,点击这条请求,然后在弹出菜单中点击 Breakpoints。现在,每到请求这个 URL 时,Charles 会暂停,这样你就可以对这个请求和响应进行修改了。
再次在 App 中下拉。
当请求发出,一个新的名为 Breakpoints 的标签页显示。不做任何修改,直接点击 Execute。再过一会,Breakpoints 标签页会在响应回来时再次显示。
点击上端的 Edit Resonse 标签。在下方,选择 JSON text。找到 temperature,将它的值修改为某个不可能的值,比如 9800。
注意:如果你在编辑请求或响应时花的时间太长,App 可能会超时,无法显示出任何内容。如果编辑完气温后没有显示,请加快动作再试一遍。
9800°F 实在是热得不行! Wunderground 无法显示超过 1000º 的气温。我想这个 App 是无法显示太阳表面的天气了。这个 App 绝对只能评为 1 星。
用 Proxy\Breakpoint Settings 惨淡删除刚才添加的断点。
反选 api.wunderground.com 去临时禁用它,或者高亮选中这行,点击 Remove 删除它。下拉刷新 App,气温又恢复了正常值。
然后,点击“小乌龟”按钮,开始调整或模拟缓慢的网络。点击 Proxy\Throttle Settings,查看有效的设置。默认是 56 kbps,非常卡的网络。通过调整这里的设置,你可以模拟出数据丢失、可靠性问题或者高延迟的情况。
刷新 App,缩放地图或者搜索其它地方。真是慢得让人痛不欲生!
这是一种测试你的 App 处于恶劣网络质量下的好办法。想一下用户在地铁上或者电梯内的情况吧?你不想让你的 App 在这种情况下丢失数据甚至崩溃吧?
苹果的 Network Link Conditioner 提供了类似功能,但 Charles 允许你更精细地控制网络设置。例如,你可以只对特定 URL 进行流量调节,以模拟你的服务器响应缓慢,而不是所有网络连接都慢。
记得在测试完后关闭流量调节。最糟糕的莫过于,花了一个小时的调试才发现忘记关流量调节阀了!
Charles Proxy 对于调试/测试自己的 App 尤其好用。例如,你可以检查服务器的响应,确保 JSON 中的 key 定义正确,所有字段中的数据类型都正确。你甚至可以用流量调节阀模拟糟糕的网络连接,检验 App 中的超时处理和错误处理逻辑。
你可以用一个 iMessage App “Charles in Charge”来进行测试,这个 App 是我专为本教程编写的。
如果你是一个 80 后,你可能知道曾经流行的 Scott Baio 主演的漫画 Charles in Charge。“Charles in Charge” iMessage app 使用了微软必应的 Image Search API 来提供能够在 iMessage 中发送的人物图片。你首先需要创建一个免费的必应 Image Search API key,以用于示例 App。首先在这里注册一个微软 Cognitive Services 账号。打开你的邮箱,然后点击检验链接,完成注册。为了生成 API key,这是必须的。
注册完毕,在账号信息页,点击 Get Started for Free 或者 Subscribe to new free trials 链接(使用哪一个取决于你是如何进入该页的);勾选 Bing Search - Free,点击 I agree next to the terms and conditions,然后点击 Subscribe。
订阅之后,你会获得两个 key。点击旁边的一个 copy 链接将它拷贝到剪贴板,等会会用到。
然后,下载Charles in Charge。用 Xcode 打开 CharlesInCharge.xcodeproj。
展开 MessagesExtension 文件夹,你会看到几个 Swift 文件。
CharlesInChargeService 负责调用必应来搜索图片,然后用 ImageDownloadService 下载这个 App 中要用到的每张图片。
在 CharlesInChargeService 的 findAndDownloadImages(completion:) 方法中,你会看到 BingImageSearchService 的初始化方法中,subscriptionKey 参数指定了一个空字符串。
将你从微软 Cognitive Services 网站上拷贝的 API key 粘贴到这里。
在模拟器中运行 App 进行测试。
注意:请在编译之前,确保 scheme 选择的是 MessagesExtension scheme。
在 Charles 中,点击 Proxy ,将 macOS Proxy 打开 (如果没有打开的话)。
然后点击 Proxy\SSL Proxying Settings ,将 api.cognitive.microsoft.com 添加到列表中。
然后在模拟器中,安装 Charles Proxy SSL 证书,以便能够代理 SSL 请求。先关闭模拟器。在 Charles 中,点击 Help\SSL Proxying\Install Charles Root Certificate in iOS Simulators(安装Charles 根证书到模拟器中)。
返回 Xcode,在模拟器中运行 App。当 iMessage 打开,找到 Charles in Charge 并选择它。等待图片加载……然而什么也没发生!怎么回事?
在控制台窗口,你会看到:
Bing search result count: 0
这表明 App 没有找到任何结果,或者数据无法解析。
首先检查你有没有从后台 API 获得数据。
在 Charles 中,在过滤器中输入 cognitive 以便轻松看到 Bing Image Seearch 请求。点击列表中的请求,选择 Response 标签页,选择底部的 JSON 文本。查看 JSON 内容,你会发现实际上搜索结果成功返回了。
因此,问题肯定出在 BingImageSearchService 中。
在 Xcode 打开这个类,查找到将搜索结果映射为 SearchResult 结构的代码:
guard let title = hit["name"] as? String, let fullSizeUrlString = hit["contenturl"] as? String, let fullSizeUrl = URL(string: fullSizeUrlString), let thumbnailUrlString = hit["thumbnailurl"] as? String, let thumbnailUrl = URL(string: thumbnailUrlString), let thumbnailSizes = hit["thumbnail"] as? [String: Any], let thumbnailWidth = thumbnailSizes["width"] as? Float, let thumbnailHeight = thumbnailSizes["height"] as? Float else { return nil }
啊哈?SearchResult 会在某个 key 不存在时返回为 nil。将这些 key 和 Charles 中的响应数据进行对比,终于找到了问题:大小写错了。
如果你眼睛够尖,你会发现,contentUrl 和 thumbnailUrl 在解析时没有将 U 大写。修改成正确的 key,然后再次运行 App。
搞定!现在,“Charles 当家”!
曾经,Charles 创建了一个可以在所有人设备上使用的证书。不幸的是,Charles 现在会创建单独的证书。这能减少利用这个证书进行“中间人攻击”的概率,但那只是相对于技术手段来说而已。因此,你应当牢记,在使用完之后删除这个 Charles 证书。
首先,从 macOS 上删除证书。从 Application\Utilities 文件夹中打开钥匙串程序。在搜索栏中输入 charles proxy,从搜索结果中将所有证书删除。当然很可能只需要删一个证书。删完后关闭钥匙串程序。
然后从 iOS 设备中删除证书。打开设置 App,找到通用\描述文件和设备管理。在配置描述文件中,你会看到 1 个或多个和 Charles Proxy 相关的条目。点开一个条目然后点击删除描述文件。重复同样步骤删除所有 Charles Proxy 证书。
在 iOS 模拟器中,描述文件和设备管理是无效的。要删除 Charles 证书,只能通过模拟器菜单下的“重置内容和设置”来重置模拟器。
希望你喜欢这篇 Charles Proxy 教程!Charles Proxy 还有许多功能和细节没有在本文中涉及。更多内容请参考Charles 官网。你使用 Charles 的时间越长,你就会发现更多的功能。你可以下载完成后的带有正确 JSON 格式的Charles in Charge App。
你还可以参考维基百科关于 SSL/TLS 的解释。苹果极有可能最终要求所有 App 使用安全网络连接,因此你应该尽快实现它。
另外,在 macOS 下还可以使用 Paw。它和 Charles 是天生的一对,用于创建新的 API 请求和测试参数。
你还知道别的网络调试工具吗?或者你有一些调试经验需要分享?请在下面分享出来吧!
79736 篇文章