我的第一个商业项目,交易金额为 2K,所以命名为 Project 2K,
本项目由 Objective-C 对应的 iOS 端以及 PHP 对应的 API 端组成,
分别由 CPY 和我完成,历时3个周末,下面我就来总结下这个项目收获的一些经验以及教训。
前期沟通
对于程序员来说,开始码代码之前必须要有一个计划,而这就与前期的沟通密切相关,我的确也是在这个地方栽跟头了。由于客户一开始提的要求特别简单,报酬相对于这个要求来说是很高的,Howerver,没有签合同,没有提前定下整体方案,于是第一个初版做出来之后,由于涉及到安全问题不能获取 UDID,最后折中使用了 IDFA,这个问题解决后,客户说我们的提交的数据没加密,服务器的返回信息是固定值,不安全,于是又改改改,让 CPY 置入了 RSA 加密,然后又踩了一个大坑,废了一个五·一(后文会讲)。好了,加密没问题了,程序的显示效果又不满意,又改改改改,这个问题解决了,又涉及到 Dylib 注入 iOS 程序的问题,毫无这方面经验的 CPY 只能一步步摸索,最后应该是解决了能发现的问题,但是程序 POST 到服务器的信息是空值,最终在我连夜 Debug 下,才让这个项目起死回生。
IDFA
IDFA —— 广告标示符,适用于对外:例如广告推广,换量等跨应用的用户追踪等。
是 iOS 6 中另外一个新的方法,提供了一个方法 advertisingIdentifier,通过调用该方法会返回一个 NSUUID 实例,最后可以获得一个 UUID,由系统存储着的。不过即使这是由系统存储的,但是有几种情况下,会重新生成广告标示符。如果用户完全重置系统((设置程序 -> 通用 -> 还原 -> 还原位置与隐私) ,这个广告标示符会重新生成。另外如果用户明确的还原广告(设置程序-> 通用 -> 关于本机 -> 广告 -> 还原广告标示符) ,那么广告标示符也会重新生成。关于广告标示符的还原,有一点需要注意:如果程序在后台运行,此时用户“还原广告标示符”,然后再回到程序中,此时获取广 告标示符并不会立即获得还原后的标示符。必须要终止程序,然后再重新启动程序,才能获得还原后的广告标示符。
在同一个设备上的所有 App 都会取到相同的值,是苹果专门给各广告提供商用来追踪用户而设的,用户可以在 设置>隐私>广告追踪 里重置 IDFA
#import <AdSupport/AdSupport.h>
NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
RSA 加密
这里推荐使用 Objective-C-RSA,这个项目提供了 iOS 端和 PHP 端的加解密,而且传输过程前能自动进行 Base64 加密,满足需求。
具体的使用方法会单独发文章讲述。
PHP 单双引号转义问题
提交数据经过 Base64 加密后,提交给服务器结果却无法解密,一开始是我的锅,PHP 单引号中 ‘\n’ 是没有被转义换行的!!必须使用双引号 “\n”,否则证书就挂了,在使用 openssl_private_decrypt($src, $out, $private_key);
的时候会提示私钥无效。
Base64 加密后传输问题
排除完 PHP 单双引号转义问题后,仍然不能解密,但是 Postman 发送的请求是可以正常解密的,经过 Debug,我们发现从 iOS 端提交的 Base64 加密的数据在传输的过程中 +
会变成空格。解决方法有两种:一种是改进 iOS 端,在提交前进行 urlencode 编码,然而对于这个库来说并不容易修改,所以我从 PHP 端进行改进,使用str_replace($find,$replace,$string);
将空格替换成 +
[highlight]$_POST[‘strings’] = str_replace(” “, “+”, $_POST[‘strings’]);[/highlight]
这样就能正常解密了。
KeyChain 无法访问
涉及到 Dylib 注入 iOS 程序的问题,我也很无奈,当时抓包发现 iOS 端 POST 到服务器上的数据为空,CPY 因为是 iOS 10 的设备,不方便看系统日志,当时认为是由于不能加载 SpringBoard.h,因而无法获取某个值,就导致了提交的字符串为空的问题,当时听 CPY 说这个项目根本不可能在未越狱的设备上跑,项目濒临失败边缘。
就在即将放弃的前,我们突然得知,客户第一份注入 Dylib 的程序是可以 POST 数据的,但是后面的版本都没有办法 POST 了。我定位到了这个 Dylib 及其代码,但是并没有找到什么收获,后来,我把这两份程序装入 iOS 9 的设备中,分析日志和POST的数据,我发现有这一串日志是最新版生成的错误信息。
然后发现,这都是由于没有权限访问 KeyChain 造成的,可是,程序提交的时候没有在中途写入 KeyChain,后来,我定位到 RSA.m,这个库需要将公钥写入 KeyChain。
那么需要如何才能访问 KeyChain,对于重签名的 ipa,需要使用下列命令重新签名
codesign --preserve-metadata=identifier,entitlements,resource-rules -f -s "iPhone Developer: XXXXX (XXXXXXXXXX)" "Yourapp.app"
这样就能访问 KeyChain 了。
果然,重新签名的 ipa 最新版也能正常 POST 数据了。
2017 年 5 月 6 日,如愿拿到了 2K,分给了 CPY 1K。
文章最后修订于 2017年9月9日
喜欢你做的尝鲜派的那个网站,如果可以,能不能发我一份呀。谢谢~~~ 😉
@Gavin: 不好意思 这个项目不开源