iOS内网自由安装测试包

自动打包脚本有了就想着打了包就直接通过脚本上传到服务器,让测试直接下载,别来打扰我最好。

但是我们的服务器用的是阿里云存储服务,Python的OSS2模块必须要AccessKeySecret来验证,所以就没有使用外网服务器。mac又自带Apache那就打个内网服务器来实现需求。

调研

iOS系统提供itms-services协议来安装ipa包,命令为:

itms-services://?action=download-manifest&url=***.plist

url是一个plist文件的获取地址,在iOS7.1以后必须用https来获取,否则会提示无法安装应用程序,因为证书无效。

那么,
第一步就是用mac自带的Apache搭建一个支持https协议的服务器;
第二步就是关于这个plist文件的配置;
第三步就是读者通过各种姿势玩这个安装命令了。

Apache配置

使Apache支持https协议的大致流程是:

  1. 创建一个颁发机构CA
  2. 用CA为你的内网服务器创建证书
  3. 开通Apache相应的服务
  4. 把CA证书导出作为邮件的附件发送至需要自由安装的设备,iOS设备可以通过附件直接安装CA证书,设置信任该证书即可

因为下列命令都必须管理者权限,所以先进入管理者模式

sudo su

1. 创建颁发机构CA

1.1. 生成CA密钥
openssl genrsa -des3 -out ca.key 1024

会要求输入访问密码(最少4位,记住以后会用),可以发现当前文件夹生成了一个ca.key的文件,1024应该是复杂度

1.2. 生成CA证书(创建颁发机构CA)
openssl req -new -x509 -days 365 -key ca.key -out ca.crt

在输入ca.key的访问密码后,会要求输入该证书的信息,因为别人不可能用你的CA,所以乱输也没事啦:

  • Country Name (2 letter code) [AU]:CN
  • State or Province Name (full name) [Some-State]:Sichuan
  • Locality Name (eg, city) []:Chengdu
  • Organization Name (eg, company) [Internet Widgits Pty Ltd]:Developer
  • Organizational Unit Name (eg, section) []:Eason
  • Common Name (e.g. server FQDN or YOUR name) []:EasonLeo(这里和下面创建服务器证书有区别)
  • Email Address []:1003004733@qq.com(提臀迎众基)

可以发现当前文件夹生成了一个ca.crt的文件,这个文件可以保留,以后创建各种自签名证书时使用,避免需要设备重复信任(在后面会说到)

2. 创建服务器证书

2.1 生成服务器证书密钥
openssl genrsa -des3 -out server.key 1024

同上,生成了server.key

2.2 获取服务器证书请求文件csr(CertificateSigningRequest)
openssl req -new -key server.key -out server.csr

需要server.key的访问密码,iOS开发者中心请求证书时同样也用了csr文件。
这里会和上面在生成CA证书时一样需要配置证书信息,其他的都一样,但是有个不同的地方

  • *** Common Name (e.g. server FQDN or YOUR name) []:*** 192.168.0.250
    (这里比较重要,是你的域名(可以通过http-vhosts.conf配置一个超炫的域名哟,虽然没卵用)或IP地址,因为我们是搭建内网服务器,所以你需要先设置一个固定的内网IP,在WIFI-高级-TCP/IP里设置,再在这里填入,否则无法连接)
2.3 获取服务器证书
openssl ca -days 365 -keyfile ca.key -cert ca.crt -in server.csr -out server.crt

这就是从CA颁发证书的命令,但因为这个命令不全所以还有一步

mkdir ./demoCA
mkdir ./demoCA/newcerts
touch ./demoCA/index.txt
touch ./demoCA/serial
echo 01 > ./demoCA/serial

再运行CA颁发证书的命令就会出现你请求证书的详情。
会询问你是否签名该证书,那肯定是 y 啊!
会再次询问你签了的证书是否提交,那肯定是 y 啊!
好了,当前文件夹下生成了server.crt证书就是服务器需要的证书,demoCA文件夹里的可以不用管,应该是一些签名记录之类的文件。

总结:生成证书流程为key -> csr -> crt,即先生成key;再用key生成csr;将csr发送给权威CA,或自建CA获取crt。

3.开通Apache相应服务

** 以下注释大多是猜想,没能找到权威说明 **

编辑/etc/apache2/httpd.conf文件,去掉下面三行前面的#号,即开通服务
LoadModule ssl_module libexec/apache2/mod_ssl.so
// 看mod名字不难理解吧。。。
Include /etc/apache2/extra/httpd-ssl.conf
// 允许配置SSL
Include /etc/apache2/extra/httpd-vhosts.conf
// 允许配置端口信息

编辑/etc/apache2/extra/httpd-ssl.conf文件,去掉下面两行前面的#号
SSLCertificateFile "/etc/apache2/ssl/server.crt"
// 证书存放位置,注意前面生成的server.crt就得存放在这设置的路径
SSLCertificateKeyFile "/etc/apache2/ssl/server.key"
// 同上,证书私钥存放位置

编辑/etc/apache2/extra/httpd-vhosts.conf文件,在文件末尾增加

<VirtualHost *:443>
    SSLEngine on
    // 打开SSL
    SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
    // 密钥解析(一本正经地胡说八道^_^)
    SSLCertificateFile /etc/apache2/server.crt
    // 注意路径!
    SSLCertificateKeyFile /etc/apache2/server.key 
    // 注意路径!
    ServerName 192.168.0.250    
    // 和生成证书的域名或IP地址一致哦,就是重点标注的那里
    DocumentRoot "/Library/WebServer/Documents"
    /* 192.168.0.250的根路径注意只有httpd.conf里的DocumentRoot之
       后的节点才有权限访问,比如httpd.conf的DocumentRoot
       是"/Library/WebServer/Documents",这里的DocumentRoot
       是"/Library/WebServer",那么只有192.168.0.250/Documents/***        
       这样的路径才有权限访问。
       如果这里改成"/Library/WebServerSB",那么你前面做这么多都白做了^_^。
      */
</VirtualHost>

自此运行一下命令

apachectl configtest

看下报什么错,我记得会报一个mod_socache_shmcb的错误,不难发现报的错是这个模块没开通,去httpd-conf取消LoadModule...mod_socache_shmcb.so前面的#号就好,当然可能还有其他错误,因httpd-conf这个配置文件而异,有问题就百度吧~

最后在configtest通过,打印Syntax OK后,重启Apache服务器,操作命令

apachectl start    // 开启
apachectl stop     // 关闭
apachectl restart  // 重启

待自由安装测试包的设备信任证书

通过邮件附件发送证书(CA证书、CA证书、CA证书,三遍)到设备自带的邮件APP上,一般邮件APP绑定了icloud账号的,所以邮件收件人可以填设备的icloud邮箱。当然你也可以在设置里增加邮箱账号,这个比较麻烦,有需要再问吧。

安装证书以后,需要到 通用->关于本机->信任的证书 里去打开该证书的开关,哎,当初忘了这一点,妈的翻来覆去地想就觉得我的理论应该正确了啊,为啥还不能信任我的https协议,在多次安装证书后发现系统在安装确认的时候就说了需要去打开开关。可能系统版本比较低的设备没有这个需要,所以请在安装证书的时候仔细阅读描述!

Plist文件配置

哎呀,直接代码吧

<?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>https://192.168.0.250/ios/developer/test.ipa</string>
                </dict>
                   <dict>
                   <key>kind</key>
                   <string>display-image</string>
                   <key>needs-shine</key>
                   <true/>
                   <key>url</key>
                   <string>https://192.168.0.250/ios/developer/icon.png</string>
               </dict>
               <dict>
                   <key>kind</key>
                   <string>full-size-image</string>
                   <key>needs-shine</key>
                   <true/>
                   <key>url</key>
                   <string>https://192.168.0.250/ios/developer/fullimage.png</string>
               </dict>
            </array>
            <key>metadata</key>
            <dict>
                <key>bundle-identifier</key>
                <string>com.developer.eason</string>
                <key>bundle-version</key>
                <string>1</string>
                <key>kind</key>
                <string>software</string>
                <key>title</key>
                <string>自由安装测试</string>
            </dict>
        </dict>
    </array>
</dict>
</plist>

将Plist文件放在DocumentRoot的某个路径下,比如我的DocumentRoot是"/Library/WebServer/Documents"并且plist文件放在"/Library/WebServer/Documents/ios/developer/下",那么itms-services协议的安装命令就是:

itms-services://?action=download-manifest&url=https://192.168.0.250/ios/developer/mainfest.plist

通过这个命令就可以安装测试包了,比如在产品Debug版本的个人中心里加一个版本更新按钮,事件响应就是

if let url = URL(string: "itms-services://?action=download-manifest&url=https://192.168.0.250/ios/developer/mainfest.plist") {
    assert(UIApplication.shared.openURL(url), "what the fuck?!")
}

那么,就酱。

感言

哇,终于还是开始写这些笔记了,虽然累但是有成就感啊!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352

推荐阅读更多精彩内容