一、为什么要聊这个话题
以前要想多台电脑开发真机测试或者打包发布唯一的选择就只有导入证书还是导入证书了!!但从Xcode7开始真机测试不用99美刀了,测试证书Xcode也可以自动生成了,再到Xcode8,AutoMatically manager signing(这里简称AMS)新特性的出现,这个功能的作用也就如字面理解自动管理签名。测试打包越来越方便了,一切都那么美好。但仔细想想,好像总感觉有点什么不对劲??就像ARC出来,但却不意味着我们就不用学一下MRC了,真的不用学习内存管理知识了,不然之后只会竟会埋雷!!同样的道理,可以自动签名了,但有些背后的东西不了解,踩雷的始终还是自己!(或者是坑接手的人?)
二、今天不聊概念,只聊AMS做了什么
1、当我们在以下界面选择了相应的team发生了什么
2、自动配置开发证书过程
-
Xcode会在本机钥匙串寻找team对应的开发证书,如果本地钥匙串存在该证书则加载使用
不存在:则从开发者中心寻找本机对应的开发证书,如果开发者中心没有则自动生成一个并下载到钥匙串使用;如果AMS已为这台电脑生成过开发证书,则提示如上图中的信息。
从这张图可以看出AMS为电脑生成的开发证书是会带上电脑名称的
-
出现上面提到的图中信息错误的解决方法
方法一: 可前往开发者中心证书管理页面(上图)下载本机的证书导入本机钥匙串。
方法二:直接选择revoke,但revoke会把开发者中心对应本机的证书重新生成覆盖掉,这样可以解决问题,但是会有一个隐患如果profile中存在被覆盖的本机证书对应的profile,且只有这一个证书时,该profile会因不含发布证书而变无效。这个很重要,具体会在文后关于Provisioning展开讨论。
-
配置Provisioning
Xcode会在本地寻找包含上一步得到的开发证书和项目bundle identifier(也就是APP ID)的Provisioning,Provisioning本地缓存路径为
如果存在则配置
不存在:则创建一个包含所有开发证书的Provisioning,配置工程,且写入本地Provisioning路径下,也就是截图路径。(但是好像开发中心并没有这个Provisioning,好奇怪,有待考证)。
三、自动配置发布证书过程
当我们需要导出ipa包或者上传App Store时,就开始需要发布证书了。需要注意的是:archive是不需要发布证书的,使用AMS自动配置好开发证书,就可以进行archive,到达这一步。
1、选择save for app store deployment或者save for Ad Hoc deployment或者upload to App Store发生了什么
-
Xcode自动加载发布证书
Xcode会去本机钥匙串寻找苹果账号对应的发布证书,如果存在则加载,下一步
如果不存在:从开发者中心寻找发布证书,如果不存在则新生成一个,并下载到本机钥匙串,并加载,下一步。如果存在则会出现这样的错误。
解决这个错误方案:
方法一:可选择去开发者中心下载(前提是那个发布证书是本机生成的,如果是其他人的机器生成的,下载也没用,因为没有私钥,私钥要从别人那里导出,这种情况只能去那个人的电脑钥匙串导出p12文件,关于证书和私钥的详细说明请移步后文)
方法二:选择reset,然后try again就可以了。但reset慎重,reset还是有可能会导致Provisioning无效的情况,而且别人的证书不再有效,以后进行和发布证书相关的操作,他就会面临和你现在相同的问题,如此恶性循环何必呢?
-
这是下一步
Xcode正确加载发布证书之后,会根据app id去profile下载Provisioning了,有则下载,无则自动创建一个(绑定当前app id和发布证书)并下载,但是,在这一步并不会检查Provisioning有无效,详细请看文后关于Provisioning话题。
-
结束
至此加载发布证书和Provisioning描述文件的过程完成。但也仅仅是加载完成而已!!从之前的过程也可以看出,不少操作都有可能导致加载后的发布证书或者Provisioning出现问题。如果加载的发布证书和Provisioning是正确的,一般都是能成功打包ipa和上传App Store的(至少我经历的是这样子),但是这里不排除工程其他配置的一些问题会导致接下来出现错误,比如引入了多个工程或者pod有可能产生的一些问题。
四、证书和秘钥的关系
如图所示,一个正确的开发(发布)证书是有一个秘钥的,而且使用的是RSA加密算法。如果曾经手动生成过开发(发布)证书的人应该知道,在开发者中心新建证书之前是要先在电脑钥匙串证书助理先新建一个CA请求证书,再用这个证书去申请开发或者发布证书的。但是Xcode8之后,即使我们没有自己创建过证书,Xcode也会自动帮我们新建证书了。
借用百度百科对CA证书的简要介绍 [CA证书](http://baike.baidu.com/link?url=Pjjs23GTuaZNsLSWMldy6bc1BGB_cR7a40_u0hOJJlrhUIheu1WKd-4BAes6JJb2tBCv--4weKk1tbR05lyWvyZyutQ4DIR2R4UI0Nw2fNi)
我们大概可以理解成,以前我们是需要自己申请CA申请证书的,但是现在Xcode帮我们做这件事了。用CA申请证书去申请开发、发布证书,自然是为了验证开发、发布证书是否有效。打个比方,拿之前的秘钥去验证重新新建的开发、发布证书自然是不会验证成功的。经实践,不仅不同电脑revoke、reset的证书不一样了,同一台电脑revoke、reset的证书也是不一样的。何为一样?我们在钥匙串删除证书后,去开发者中心下载证书,导入钥匙串之后,与删除前是一样的。但是如果不是一样的证书就会如图所示
这是导入的其他电脑生成的开发证书,显然,这是不包含秘钥的。自然使用不了,结果也的确这样,提示revoke
由以上也可证明一点,Xcode帮我们申请的证书(开发、测试证书)都跟电脑绑定的。如果我们想让其他电脑也能用这台电脑的证书,也只有采用老方法,导出p12文件,这样秘钥也导过去了。就可以正常使用。
五、 关于Provisioning
1、APP ID、证书、Provisioning的关系。
我们知道最终打包进去ipa的是Provisioning描述文件,而Provisioning文件则包含了开发者的开发或者发布证书,以及APP ID(可以理解为bundle identifier)。做了这么多事情,也是为了得到正确的Provisioning从而成功的打包或者上传我们的app。如果证书或者APP ID出错了,最后的Provisioning自然也是错的,签名过程自然就会出现问题
2、为什么说revoke和reset会导致Provisioning错误呢?
经过观察,Provisioning会无效会有两种情况,要么过期了,要么不含有证书了,这样在开发者中心Provisioning Profiles页面就会显示invalid无效。Xcode加载Provisioning的时候并不会验证Provisioning是否有效。也就是说,显示invalid的Provisioning,Xcode也会加载回来,且不会提示错误。这样就有可能会有问题。
举个目前发现的例子:
假如开发者中心一片空白,当在mac A打包上传时,开发者中心为该开发者创建了关联mac A的开发证书和发布证书,并且自动生成了app id和Provisioning,此时的Provisioning就是关联了发布证书的,且就一个证书,例如下图
mac A就成功打包上传了,一切都很顺利。然而过了一段日子,需要在mac B打包上传,因为mac B是没有发布证书的,自然会提示reset,如果mac B进行了reset,那么Xcode自动为mac B创建的发布证书就会替代mac A之前的证书了,原证书没了,Provisioning的Certificates就会变成0 total,从而变成invalid,无效了。但是mac B继续打包上传,在Xcode从开发者信息中寻找Provisioning的时候,因为含有同样的APP ID的Provisioning存在了,Xcode不会再为开发者重新创建一个Provisioning,而是直接加载!!而加载这个恰好就是无效的!Xcode也不会提示任何错误。那么之后就GG了。
六、题外话
这里顺便提一下App IDs,在开发者中心APP IDs有个Wildcard App ID的概念,大概的意思就是使用通配符的App ID可以通配一系列符合的APP ID;比如定义了一个Wildcard App ID:com.,那么这个App ID就可以统配所以以com.开头的bundle identifier,xcode不会再为其生成相同名字的App ID。同理,在第一次使用com. App ID时,Xcode会为其新建Provisioning,Provisioning对应的App ID就是com.,以后再有新项目bundle identifier以com.开头,Xcode不会再为其创建Provisioning,也就是公用com. APP ID的应用共用一个Provisioning。通配符有其好处,也有不好的地方,感兴趣大家可以到Apple官方看看相关内容。
-
Xcode自动为项目创建APP ID的过程
说了这么多Wildcard App ID的内容,也是为了说一下,Xcode自动为项目创建APP ID的过程。如果开发者中心有与bundle identifier相同的APP ID则不创建,如果没有,会看有没有适合的Wildcard App ID,如果有也不创建,如果没有才最后创建与bundle identifier相同ID的App ID。
七、最后的最后
那么多文字,也辛苦大家看下来了。其实说了这么多,也并没有解决什么问题!!只是个人经验,分享出来,让大家知道一下免得一不小心埋雷或踩坑了。公司项目前几天莫名其妙的能安装能使用,隔天就打开闪退,安装ipa,进度条跑完了却马上消失了。这坑也正是由于前面提到的Provisioning无效导致的。不废话了,如果有发现理解错的地方,期待大家留言评论。