Mac App公证

Mac OSX

Posted by Karim on July 8, 2020

前言

从非Mac AppStore的地方下载的App,大家应该都有遇到过这样的提示:

遇到这种情况,可以在终端输入,将安全性与隐私-通用-任何来源开启,这样就可以解决了:

$ sudo spctl --master-disable

但是作为一个普通用户,会认为你的App不安全,我开发的虚拟定位因为需要依赖非沙盒环境下的Magellan,也遇到这个问题,也有国外用户因为觉得这个行为是有风险,在AppStore给了个差评。

从设置上看,用户是可以通过选择App Store和被认可的开发者下载非App Store来源的应用的,问题是怎样才能成为被认可的开发者呢?

正文

Mac上通过Gatekeeper的技术来确保用户运行的是自己信任的App,在App Store上架之前应用是经过Apple签名的,通过这种方式保证App没有被修改。

而从第三方网站或软件中下载的App,则需要提交应用给Apple进行公证,公证结束后再对其签名,用户下载的时候弹窗就会变成这样:

公证的方式有两种,一种是通过Xcode Archives后在Organizer进行操作,另一种方式是通过脚本自定义workflow。

Xcode

通过 Xcode导航栏上方 「Product」->「Archives」,选择「Distribute App」-> 「Developer ID」-> 「Upload」

上传完成后,等苹果回复认证通过的邮件后,再次选择「Distribute App」-> 「Developer ID」-> 「Export」,这时候导出的包就是已经被苹果公证过的了。
苹果公证邮件回复的很快,官方文档提到一般一小时内会回复,我一般5-10分钟就会收到了。

Workflow

我自己用的是脚本打包,因为mac上打包主要以dmg的形式为主,另外dSYM也需要上传到App Center上,自定义workflow更适合我。

先用Xcode打包的方式执行一次,将导出后文件夹中的ExportOptions.plist复制到工程目录下,即$SRCROOT/ExportOptions.plist下,等下会用到。

新建个构建脚本文件,放工程目录下:

#App名字
PRODUCT_NAME=xxx
CONFIGURATION=Release
#SCHEME名字
BUILD_SCHEME=xxx

CLEAN_COMMAND="xcodebuild -workspace ${PRODUCT_NAME}.xcworkspace -scheme ${BUILD_SCHEME} -configuration ${CONFIGURATION} -sdk macosx"
BUILD_COMMAND="xcodebuild archive -workspace ${PRODUCT_NAME}.xcworkspace -scheme ${BUILD_SCHEME} -configuration ${CONFIGURATION} -sdk macosx -archivePath ${PRODUCT_NAME}.xcarchive"

$CLEAN_COMMAND clean
$BUILD_COMMAND

苹果不建议我们使用明文的密码,通过下面的命令,将密码放进钥匙串:
Xcode 13之后:

#这里的WWDRTeamID,其实是你的开发者账号的team id,可以通过https://developer.apple.com/account 「Membership」查看
xcrun notarytool store-credentials "AC_PASSWORD" --apple-id "开发者账号邮箱" --team-id <WWDRTeamID> --password <secret_2FA_password>

Xcode 13之前:

xcrun altool --store-password-in-keychain-item "AC_PASSWORD" -u "开发者账号邮箱" -p "apple id专用密码"  

不知道什么是专用密码的,可以看这里

将下面的脚本调整后,放入Post-actions中

xcodebuild -exportArchive -archivePath "$ARCHIVE_PATH" -exportOptionsPlist "$SRCROOT/ExportOptions.plist" -exportPath "$EXPORT_PATH"

APP_PATH="$EXPORT_PATH/$PRODUCT_NAME.app"
ZIP_PATH="$EXPORT_PATH/$PRODUCT_NAME.zip"
#如果不是打包成dmg,.app需要压缩成zip上传
ditto -c -k --keepParent "$APP_PATH" "$ZIP_PATH"

接着将压缩好的zip文件,上传到苹果服务器进行公证,Xcode 13之后:

#使用--wait,告诉notarytool只有在公证服务完成处理提交后才退出
#如果你想公证处理提交后得到一个回调,可以使用--webhook指定一个url
xcrun notarytool submit $ZIP_PATH
                   --keychain-profile "AC_PASSWORD"
                   --wait
                   --webhook "https://example.com/notarization"

Xcode 13之前:

#这里的ProviderShortname,其实是你的开发者账号的team id,可以通过https://developer.apple.com/account 「Membership」查看
xcrun altool --notarize-app --primary-bundle-id "com.bundle.id" --username "AC_USERNAME" --password "@keychain:AC_PASSWORD" --asc-provider <ProviderShortname> --file $ZIP_PATH

上传完之后,控制台上会打印RequestUUID,如果不成功或者想查询审核状态都需要这个id,也可以通过后面查询当前所有请求状态的命令查到RequestUUID
审核通过后,对app签入公证即可:

xcrun stapler staple "xxx.dmg"

查询当前所有请求状态

xcrun altool --notarization-history 0 -u "AC_USERNAME" -p "@keychain:AC_PASSWORD"

会返回你所有请求的状态

Notarization History - page 0

Date                      RequestUUID                          Status      Status Code Status Message  
------------------------- ------------------------------------ ----------- ----------- ----------------
2018-07-02 20:32:01 +0000 2EFE2717-52EF-43A5-96DC-0797E4CA1041 invalid     2           Package Invalid 
2018-06-29 13:23:13 +0000 6D020E28-9890-48E5-851C-4275169D07CC invalid     2           Package Invalid

查询某个请求的详细信息

xcrun altool --notarization-info $替换成自己的RequestUUID -u "AC_USERNAME"

如果有审核有问题,LogFileURL会提供日志文件,指出发现的问题,修改完后重新提交即可。

   RequestUUID: 2EFE2717-52EF-43A5-96DC-0797E4CA1041
          Date: 2018-07-02 20:32:01 +0000
        Status: invalid
    LogFileURL: https://osxapps.itunes.apple.com/...
   Status Code: 2 
Status Message: Package Invalid

写在最后的一些感触

虽然是个并不麻烦的事情,但是很多大厂的App都没有做这个,感觉都是国内用户惯的,需要用户去适应App,而不是App迎合用户。

参考链接

Notarizing macOS Software Before Distribution
Signing Your Apps for Gatekeeper
Safely open apps on your Mac
Customizing the Notarization Workflow


请保持转载后文章内容的完整,以及文章出处。本人保留所有版权相关权利。

分享到: