超级签名指的是使用苹果个人开发者账号,将adhoc包分发给线上玩家的操作。为什么需要超级签名?原因是绕过appstore的方式有两种:
1. 使用企业包
2. 使用adhoc包
企业包的弊端是频繁掉签,掉签后,玩家无法登陆游戏,提示未受信任的开发者。其次,企业账号申请困难,市面上企业账号已经被炒到几十万RMB。好处显而易见,一个账号就可以搞定所有地区。
adhoc包,adhoc包无法自主安装,需要在苹果后台添加设备信息后,指定设备才可以安装ipa。缺点是无法大面积分发给用户自主安装,并且一个个人开发者账号,只能安装100台设备。优点是稳定不掉签。
实现adhoc包技术难点:
1. 如何获取UDID
2. 如何将获取到UDID,上传到苹果开发者中心(总不能手动添加吧)
3. 如何将包含UDID列表的描述文件下载下来
4. 如何使用下载的描述文件重新签名ipa包
首先如果获取UDID?
苹果允许通过安装mobileconfig 描述文件的方式,获取到UDID信息,通过Safari下载预先生成描述文件,下载完成后系统弹出询问是否安装,这里肯定选择安装,安装完成后,系统会重定向到描述文件中指定的服务器,并携带者UDID等信息。(这个下载地址与回调地址一定要是HTTPS协议的)
<?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>PayloadContent</key><dict><key>URL</key><string>https://complain.jnxgame.com/hallex/report/uuid.do</string> <!--接收数据的服务器接口地址--><key>DeviceAttributes</key><array><string>UDID</string><string>IMEI</string><string>ICCID</string><string>VERSION</string><string>PRODUCT</string></array></dict><key>PayloadOrganization</key><string>XXXX--【点击安装】</string> <!--组织名称--><key>PayloadDisplayName</key><string>申请设备信息</string> <!--安装时显示的标题--><key>PayloadVersion</key><integer>1</integer><key>PayloadUUID</key><string>3C4DC7D2-E475-3375-489C-0BB8D737A653</string> <!--自己随机填写的唯一字符串--><key>PayloadIdentifier</key><string>dev.skyfox.profile-service</string><key>PayloadDescription</key><string>本文件仅用来获取设备ID</string> <!--描述--><key>PayloadType</key><string>Profile Service</string></dict></plist> |
如何上传设备信息,下载描述文件?
工具地址:https://github.com/fastlane/fastlane/
如何重签IPA
工具地址:https://github.com/zhlynn/zsign
关键步骤都解决了,开始部署到Linux。(下图是超级签名实现流程)
遇到问题:
- mobileconfig 签名问题,如果不签名安装时候会提示描述文件未签名。
解决办法:找运维获取到要部署的https服务器的ca证书文件,公钥私钥证书文件,使用openssl 进行签名。 - 苹果账号登录需要 2FA认证,如何实现?
解决办法:利用fastlane spaceauth 提前登录到苹果后台,输入手机验证码或digit码后,保存返回的FASTLANE_SESSION,到服务器上设置环境变量。注意:SESSION30天过期。
附件:
# author: ruiqingliang
# version: 0.1
# lastUpdateTIme: 2019-1-10
# address: ruiqingliang@sina.comrequire "spaceship"result = 0
begin # # 命令行获取参数AppleAccount = ARGV[0]ApplePassword = ARGV[1]AppleBundleId = ARGV[2]DeviceName = ARGV[3]DeviceUDID = ARGV[4]puts "#{AppleAccount}\t#{ApplePassword}\t#{AppleBundleId}\t#{DeviceName}\t#{DeviceUDID}"Spaceship::Portal.login(AppleAccount, ApplePassword)device = Spaceship::Portal.device.create!(name: DeviceName, udid: DeviceUDID)# 获取指定的描述文件,更新测试设备信息filtered_profiles = Spaceship::Portal.provisioning_profile.ad_hoc.find_by_bundle_id(bundle_id: AppleBundleId)filtered_profiles.collect do |_profile|puts _profile.name_profile.devices = Spaceship.device.all_profile.update!endputs "#{Time.now} 账号创建成功:#{device.name} #{device.udid}" rescue Exception => e puts "#{Time.now} 账号创建失败,原因:#{e.message}" afile = File.new("rubylog.txt", "a+")afile.syswrite("#{Time.now} 账号创建失败,原因:#{e.message}\n")afile.closeresult = 1
endexit(result) |
# author: ruiqingliang
# version: 0.1
# lastUpdateTIme: 2019-1-10
# address: ruiqingliang@sina.comrequire "spaceship"
require "json"result = 0
begin # 获取配置信息AppleAccount = ARGV[0]ApplePassword = ARGV[1]AppleBundleId = ARGV[2]DownloadFolder = ARGV[3]puts "profile download:#{AppleAccount}\t#{ApplePassword}\t#{AppleBundleId}\t#{DownloadFolder}"Spaceship::Portal.login(AppleAccount, ApplePassword)# Download a specific profile as filematching_profiles = Spaceship::Portal.provisioning_profile.ad_hoc.find_by_bundle_id(bundle_id: AppleBundleId)first_profile = matching_profiles.firstFile.write("#{DownloadFolder}/output.mobileprovision", first_profile.download)puts "#{Time.now} 描述文件下载成功"
rescue Exception => e puts "#{Time.now} 描述文件下载失败,原因:#{e.message}" afile = File.new("rubylog.txt", "a+")afile.syswrite("#{Time.now} 描述文件下载失败,原因:#{e.message}\n")afile.closeresult = 1
endexit(result) |