本文转载自
链接 http://blog.csdn.net/close_marty/article/details/38441903
作者 close_marty
最近设计的同事找到我,说有没有什么方法可以很方便的获取和安装我们应用最新的测试包,然后还给我看了别人通过微信朋友圈分享测试包的做法。好吧,虽然我手头没有外网服务器,那我就在内网搭一个吧,然后先在内网实现通过wifi直接安装测试包。
首先大概说下OTA吧,OTA就是over the air,是一种无线发布方式,它可以实现app的在线安装,不再需要数据线。目前国内有不少团队通过使用企业证书+OTA的方式来发布自己的应用,所以你会看到有的网页上有某个应用的广告,你点击之后就直接提示你是否安装这个app,一旦你确定,它就直接在你的手机上安装了,这中间完全没有经过appstore的参与和审核。这也是实现在不越狱的手机上安装未经审核app的方法。不过我们自己的测试包都是使用开发者证书来打包的,所以只有指定的设备才可以安装。
要实现OTA,需要准备下面这三个文件,然后把他们放到自己的web服务器上,通过访问你的web页面来实现在线安装。
*.ipa文件,也就是你的安装包,可以是开发者证书签名的,也可以是企业证书,看你的用途和目的
*.plist文件,这个描述文件主要是用来说明应用的安装信息的,下面一个简单的sample
<?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>items</key>
<array>
<dict>
<key>assets</key>
<array>
<dict>
<key>kind</key>
<string>software-package</string>
<key>url</key>
<string>http://${YOUR_DOMAIN_DOTCOM}/${PATH_TO_BETA_IF_ANY}/${APPLICATION_NAME}.ipa</string>
</dict>
</array>
<key>metadata</key>
<dict>
<key>bundle-identifier</key>
<string>${BUNDLE_IDENTIFIER}</string>
<key>bundle-version</key>
<string>${APPLICATION_VERSION}</string>
<key>kind</key>
<string>software</string>
<key>title</key>
<string>${DISPLAY_NAME}</string>
</dict>
</dict>
</array>
</dict>
</plist>
其中指定了ipa文件的具体存放路径。这个plist可以在打包的过程中自动生成,具体方法可以参考这里,我不再赘述
http://aaronparecki.com/articles/2011/01/21/1/how-to-distribute-your-iOS-apps-over-the-air
也可以通过正常流程打包完ipa包之后,根据ipa文件来生成plist文件,可参考第三方的工具
https://github.com/sveinungkb/ios-ota-buddy
还可以自己手动去编写这么一个文件或者自己写个脚本去生成,只要包含这些主要信息即可。
- 一个或简单或复杂的发布页面,目的是提供一个itms-services协议的链接,让用户访问这个链接即可实现在线安装。一个最简单的html页面就是下面这样。
<a href="itms-services://?action=download-manifest&url=https://xxx.xxx.xxx/xxx.plist">Install App</a>
整个OTA的核心就是苹果的itms-services协议, safari通过解析类似于itms-services://?action=download-manifest&url=https://xxx.xxx.xxx/xxxx.plist 这样的一个链接来实现在线安装。url就是你的*.plist文件所在的地址,在iOS7.1以前,这个url是没有限制的,在7.1之后,苹果做了修改,要求这个url必须是可信任的https链接。其他地方的链接并没有要求。
对于https链接,目前主流的有三种解决方案。
方案1:交给公司解决,让公司提供一个可信的https连接,这个最直接。
方案2:采用第三方的网站提供的https连接,比较常见的就是把plist上传到dropbox,然后分享出去,它的外链就是https的(不过dropbox已经被墙了,so...),国内网盘的外链貌似都是http的,基本可以忽略
方案3:使用自建的https连接
我们是个小团队,采用的方案3,但是这里有个问题,https是需要有证书的,而可信的证书必须是由知名的CA所颁发,当然,向这些知名的CA申请证书是需要money的。由于我使用OTA的目的只是在团队内部分发一下测试包而已,所以我们采用自签名的证书来加密https。
自签名分为两个步骤,首先生成自己的CA根证书,再用这个根证书去签名我们服务器所使用的证书。
- 生成自己的根证书
生成自己的密钥对
openssl genrsa -out ca.key 1024
生成证书请求文件,并使刚刚的key来加密CA根证书
openssl req -new -x509 -days 365 -key ca.key -out ca.crt
其中-x509选项表示生成自签名的证书,生成证书会要求填一系列的东西,此时可以任意填写,也可以直接回车,Common Name (e.g. server FQDN or YOUR name) []:,这一项建议填写一个便于识别的名字,比如可以是你的名字或者代号。
完成到这里你就已经生成了自己的根证书了,你也和那些知名CA机构一样,用根证书给别人的证书签名啦。。撒花。。。不过由于你不知名,没有人会认可你的证书,所以你签名的所有证书都是不会被信任的。
- 生成服务器使用的证书,并用自己的根证书签名
步骤基本同上:
生成一个密钥对
openssl genrsa -out server.key 1024
生成证书请求文件
openssl req -new -key server.key -out server.csr
这里又需要填写之前的那一堆东西,值得注意的是,
Common Name (e.g. server FQDN or YOUR name) []:
这里一定要填写你的https连接所对应的域名或者是服务器Ip, 比如xxx.xxx.com或者是192.168.25.68这样。
接下来我们需要使用根证书对这个证书进行签名,但是在签名之前,需要做一些准备工作, 我们需要构建这样一个目录结构,在当前目录新建文件夹demoCA,
进入demoCA,在demoCA下创建两个文件index.txt和serial ,以及文件夹newcerts,其中index.txt的内容为空,serial的内容为01。
完成之后,就可以开始签名了
openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key
openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key
这条命令中涉及的所有文件都是在之前步骤中生成的,如果缺少了什么文件,最好回去检查一下步骤是否有问题。
命令执行后会要求确认是否进行签名,确认即可。
到这里,证书的构造已经完成,最终的目录结构应该是这个样子
- 让iOS设备信任你的根证书
之前说过了,自签名的证书是不可信的,所以你需要让通过OTA方式来安装app的手机去信任你的证书。
方式1:把你的根证书文件,也就是ca.crt 放到web服务器的某个位置,然后iOS设备通过safari去访问这个文件就会直接提示用户安装证书,点击安装即可。(只能是safari,不能是其他浏览器)
方式2:通过email方式,把ca.crt作为附件通过邮件发送到iOS设备上,然后也可以打开安装
方式3:其他我不知道的方式,比如什么iPhone配置实用工具之类的,总之呢,就是让iOS设备去打开并安装ca.crt这个文件。
我采用的方式1,我把ca.crt的url和itms-services链接一起放在一个简单的发布页面install.html里面的,然后把html的地址生成个了一个二维码,发给大家。其他人扫描二维码,访问这个页面,然后点击两下,第一下安装证书,第二下安装app,就可以搞定了。
安装之后,这个证书文件就会变为可信的了。可以在iOS设备上的通用-描述文件中查看这个证书的状态。
- 修改itms-services协议中的url为https
比如itms-services://?action=download-manifest&url=https://172.16.8.53/OTA-Install/xxxxxxx..plist,当然如果已经是https的,那就不用改了。
至于ipa文件是否使用https并不重要,苹果只要求itms-services协议中的url字段使⽤用https。
至此就可以在iOS7.1及以上的设备中通过OTA方式安装了。
附1:
前面的 openssl req 和 openssl ca 命令,有可能需要增加一个config参数
-config ..\conf\openssl.cnf
不过我没有加,所以默认使用的
Using configuration from /System/Library/OpenSSL/openssl.cnf
附2:Apache服务器的openssl配置(mac OSX 环境)
- 确保 httpd.conf 中 LoadModule ssl_module 这项设置是有效的
- 在 httpd-ssl.conf 中,确保下⾯面的配置有效,并且对应的crt和key文件正确(这两个文件就是我们之前自己生成的服务器使用的证书和密钥)
SSLCertificateFile "/private/etc/apache2/ssl/server.crt"
SSLCertificateKeyFile "/private/etc/apache2/ssl/server.key" - 记得重启服务器
- 检查https是否生效可以访问 https:localhost