macOS

超越沙盒限制:不透過 Mac App Store 都可以簽署並發佈 macOS App !

超越沙盒限制:不透過 Mac App Store 都可以簽署並發佈 macOS App !
超越沙盒限制:不透過 Mac App Store 都可以簽署並發佈 macOS App !
In: macOS

因為 OS X Mojave(特別是 Catalina)問世、以及 Apple 對 App 公證 (Notarization) 的要求,讓我們這些資深的 macOS 開發者開始擔心,Apple 會否禁止開發者自行發佈 App 的流程。你們可能都曾經試過在網站上直接下載 macOS 軟件,也就是說不需要從 Mac App Store 來下載。但是你有仔細想過這件事嗎?

我們無法從 iOS App Store 以外的地方下載 iOS App;雖然有 Apple Developer Enterprise Program 這種特別情況,不過那只能夠允許大型組織開發內部專用的 App,並且配置給他們的員工所使用。你有試過下載像是 SkypeZoomAtomSourcetree 這些工具嗎?他們都是不在 Mac App Store 上面發佈的「第三方」App。你也可能是在 Apple 開發者網站上下載過 Xcode 吧!(因為通常從 App Store 下載都會出現問題)

我想要和你分享我的經歷,讓你也可以不需要透過 Mac App Store,開發並且發佈 macOS App。今天,你將會瞭解 App 及其安裝檔繁複的簽署與公證程序。Apple 的簽署與公證程序可以很複雜,而且相關的文件說明也不清楚,特別是關於安裝檔的部分。

編者備註:如果你對於 macOS 開發不太瞭解,你可以參考我們的 macOS 教學文章

系列教學文章

這個系列的教學文章共有三篇,旨在說明如何在 Mac App Store 外部進行沙盒、簽屬、公證、以及發佈 macOS App。在本篇教學中,我們將會建立一個非沙盒化的 App,並討論關於憑證、簽署、公證、建立安裝檔、安裝檔的簽署與公證、以及發佈 App 的流程。在第二篇教學文章中,我們將會示範如何在範例 App 中啟用沙盒功能以及權限,並探索如何讓使用者存取 App 容器外部的資料與資料夾。我們也會討論沙盒的優缺點,並試著瞭解 Apple 為沙盒 App 提供漏洞的原因。在最後一篇文章中,我將會帶你利用一個免費 App Packages,來為你的 App 創造一個安裝檔。我們將會創建一個包含初始頁面、安裝說明、授權同意、以及相關安裝選項的安裝檔。

不經 Mac App Store 發佈 App 的優點

在 Mac App Store 之外發佈 macOS App 有幾個優點。在 Mac App Store 上發佈App,你就需要承受 Apple 善變又不透明的 App 審閱機制,有時候還會任意拒絕 App 的發佈。因此,在 Mac App Store 之外發佈 App,就可以讓你在創意、設計、開發、發佈、財務、及功能等各方面都有更多選擇。

舉例來說,你不需要將 App 沙盒化,讓存取 macOS 檔案系統的權限更自由。另一個避開 App Store 的理由,是你不需要遵守 Apple 一些讓人困惑又嚴格的使用者介面指引 (Human Interface Guidelines)。而最重要的理由,就是你可以省下許多費用!

以下是不透過 Mac App Store 來發佈 macOS App 的一些理由:

  • 你可以選擇自己喜歡的任何方式和地點,來宣傳、發佈、及銷售你的 App。
  • 不需要向 Apple 支付 30%/15% 的費用,用來銷售 App 或後續的「App 內購買」功能(你可以在 App 內銷售任何功能)。
  • 你不需要遵守使用者介面指引。
  • 你不需遭受到惡意的評論。

Gatekeeper 與公證是什麼?

在深入討論之前,讓我們先來釐清 Apple 所謂「公證」的實際意思,以及其重要性。關於 Gatekeeper,Apple 以下的描述正是我們接下來要討論的內容:

…… 當你從網路上或是開發者那裡直接下載並安裝 App 時,macOS 會繼續保護你的 Mac。而當你安裝從 App Store 外部獲取的 Mac App、擴充套件、及安裝檔時,macOS 會檢查開發者 ID 簽署 (Developer ID signature),來確認該軟件是來自於已獲認證的開發者,而且軟件沒有被更改。在預設的情況下,macOS Catalina 也會需要軟件經過公證,所以你可以信任在 Mac 上執行的程式不是惡意軟件。在第一次打開下載的軟件之前,macOS 會要求你的同意,來確保你不是被誤導而執行一些非預期的軟件。……

我的範例程式碼

讓我們開始吧!如果你想要自己建立一個專案並跟著我操作,你可以打開 Xcode (我正在使用 11.2.1 版本),並使用 macOS App 模板創建一個專案。你可以依照我的 storyboard 與程式碼作參考。或者,如果你想要使用我現有的程式碼來跟著操作,你可以打開我的 AppNotaryAndDistrib 專案,並跟著本篇文章閱讀。你可以在這裡下載我使用 OS X 10.15 (Catalina) SDK 所編譯的範例專案。如果你使用我的程式碼,記得必須要使用 Xcode 11.x 來調整相關設定,在 TARGETS -> [TARGET_NAME] -> Signing & Capabilities -> Signing 使用你自己的 TeamBundle IdentifierSigning Certificate、以及 Provisioning Profile

這次,我不會討論太多關於 Swift 程式碼的細節,因為本次教學文章的重點是在 Mac App Store 外部發佈安全的程式碼。我們將會專注於 App 的相關配置。接下來跟著我的步驟,我們將會配置、建置、簽署、並且公證我的 App,然後再配置、建置、簽署、並且公證 App 的安裝檔。當你執行安裝檔,並執行範例 App 後,你將會看到這個畫面:

Beyond the Sandbox: Signing and distributing macOS apps  outside of the Mac App Store 1

讓我們花點時間,來瞭解連結到主視窗中間 “Select folder” 按鈕的程式碼。我在前面提過,在本系列的第二篇文章,我們將會非常深入地討論使用者如何授權一個沙盒化 App 存取外部的特定資料夾。回到剛剛所討論的,簡單來說,從專案中的 NSViewController 子類別,我使用了 NSOpenPanel 來讓使用者能夠選擇一個獨立的資料夾。

...
@IBAction func selectFolderBtnClicked(_ sender: Any) {

    let folderSelectionDialog = NSOpenPanel()

    folderSelectionDialog.prompt = "Select"
    folderSelectionDialog.message = "Please select a folder"

...

    if dialogButtonPressed == NSApplication.ModalResponse.OK {

...
                    self.userSelectedFolderURL = url
                    print("User selected folder: \(url)")
...

    } // end if dialogButtonPressed == NSApplication.ModalResponse.OK

} // end func selectFolderBtnClicked
...

應用程式簽署與公證

相信大家都很熟悉構建 App、並將它提交給 iOS App Store 的過程,又或是在本篇教學文章的情況,把 App 提交並發佈到 Mac App Store 的過程。你也應該知道為什麼必須對 App 進行數位簽署 (digitally signed)。如果你還不瞭解的話,請花點時間讀一下有關憑證及簽署的資料。

簽署 App 的準備

我沒辦法涵蓋到所有 App 簽署與公證需要的元件、協定、及方法,不然這篇文章會變得非常冗長。讓我給你一些 Apple 所提供的文件,讓你可以自己在 Mac 上重現本篇教學所展示的結果。你可以閱讀 “Signing Your Apps for Gatekeeper”“Create, export, and delete signing certificates”、以及 “Distribute outside the Mac App Store (macOS)” 這幾篇文章。

因為我時常在 App Store 之外開發、簽署、公證、並發佈 macOS App,所以我 Mac 的 Keychain 當中擁有下列幾種類型的憑證。如果你想要在 App Store 之外發佈 macOS App,你需要在 Apple 開發者入口網站 (portal),透過你的帳號創造並匯出相同型別的憑證,並將它們安裝到 Mac 的 Keychain 當中。根據你在開發者入口網站的帳號資訊,TEAM_NAME 是你自己或公司的 “Team Name”,而 TEAM_ID 就會是你自己或公司的 “Team ID”。以下是我 Keychain 的相關憑證:

Developer ID Installer: TEAM_NAME (TEAM_ID)
Developer ID Application: TEAM_NAME (TEAM_ID)
Apple Worldwide Developer Relations Certification Authority
Developer ID Certification Authority

這並沒有包含所有日常開發所需的憑證,而只是對 App 和安裝檔簽署、及公證最重要的憑證而已。你要將 Developer ID 這個字牢牢記住,根據 Apple 的文件:

對於從 Mac App Store 以外的地方下載的軟件及 App,開發者可以獲取 Developer ID 憑證,並且將其軟件提交給 Apple 進行公證。要讓 Gatekeeper 驗證你的軟件不是惡意軟件、而且未被篡改,軟件需要有唯一的 Developer ID 數碼簽署、及 Apple 的公證令牌 (ticket)。

為了讓你熟悉操作,以下是 Apple 開發者入口網站的螢幕截圖,展示了如何創建要在 App Store 之外發佈 macOS App 所需的憑證。創建新憑證的時候,它將會顯示 Certificates, Identifiers & Profiles 部分:

macOS-app-distribution-create-certificate

創建了這些憑證後,你就可以把它們下載並安裝到 Mac 的 Keychain 之中。

加入自動簽署、取消沙盒化以及保持強化

我們與預設的 macOS App 模板有所不同,而其他設置就維持不變,這些設置分別就是沙盒 (sandboxing) 與強化 (hardening)。大多數開發者都會使用 Automatically manage signing 設置,我們可以在 TARGETS -> [TARGET_NAME] -> Signing & Capabilities 選擇這個設置刪,並刪除 App Sandbox 功能授權,而保留預設的 Hardened Runtime 功能(建構設定),就像是下圖這樣,注意紅色註記的部分:

automatic-signing-sandboxing

許多 App 都受惠於可以方便存取 Mac 內部(除了保護區之外)任何檔案或資料夾,因此我的 App 是沒有被沙盒化的。至於強化,根據 Xcode 11 Help 的說明:

Hardened Runtime 會保護你的 App,防止其他人修改其程式碼,並提供過程中可以執行內容的細緻度控制。除非你的 App 預先聲明要使用敏感資源,否則 Hardened Runtime 也會阻止對敏感資源的存取,這可以避免不必要的存取,減低被攻擊的機會。這些屬性可以防止別人利用 App 達到其他目的,而且這對於公證 App 也是必需的。(我標註了重點)

建置、簽署及公證

相信大家都很清楚如何清理並建置 App,但你們有沒有試過在上傳 App 到 App Store 時簽署 App,而不只是單純使用 Xcode 的自動認證功能。在這裡,我們將會手動進行數位簽署,下文將會逐步示範如何操作。以下是一個你應該非常熟悉畫面:Xcode 的 Product 選單。

Product-menu

讓我們依序執行 Clean Build FolderBuild、並點選 Archive。Xcode 的 Organizer 視窗會出現,來顯示你剛創建的 archive:

organizer-window

點選上圖中紅色方框標註的 Distribute App 按鈕,Select a method of distribution: 選單會跳出,選擇 Developer ID 選項(說明為 “Distribute directly to customers.”),如同先前我所討論到的憑證一樣。請記住 Developer ID 的重要性。接著,點選下圖中的紅色方框標註的 Next 按鈕:

Beyond the Sandbox: Signing and distributing macOS apps  outside of the Mac App Store 4

下一步就是 Select a destination: 視窗,選擇 Upload(說明為 “Send to Apple notary service.”),接著點選 Next,然後將 App 上傳給 Apple 進行公證,如下圖所示:

Beyond the Sandbox: Signing and distributing macOS apps  outside of the Mac App Store 5

你也要記住公證的重要性,你將 App 提交給 Apple 來進行安全檢驗,Apple 會檢視你的 App 有沒有惡意內容,並確認是否有程式碼簽署的問題

然後,Re-sign “[APP_NAME]”: 選單跳出,這裡的 APP_NAME 顯然就是我們想要提交去公證的 App 名稱,以我的範例 App 而言就是 “AppNotaryAndDistrib.”。接著選擇 Manually manage signing(說明為 “Select certificates and profiles from your team.”),接著點選 Next

Beyond the Sandbox: Signing and distributing macOS apps  outside of the Mac App Store 6

Select certificate and Developer ID profiles: 選單會跳出,你已經設定了 Team,現在將 Distribution certificate: 設定為合法的 Developer ID 憑證,並將 App 名稱旁邊的下拉選單配置文件設定為 “None”。因為我並沒有在 App 當中添加任何功能,所以我可以設定為 “None”。(前面提到將沙盒功能刪除,並保留強化的設定,因為在預設情況下強化是開啟的,因此它是一個建置設定,而不是一項功能。)然後,繼續點擊 Next

Beyond the Sandbox: Signing and distributing macOS apps  outside of the Mac App Store 7

現在我們進入了 Review [APP_NAME].zip content: 視窗。你可能會好奇為什麼是 .zip 格式,一個完整的 App Bundle 通常會包含一些擴充套件,雖然這次的範例沒有,不過要記住 Bundle 是一種目錄結構,通常包含了許多可以被壓縮的元素,所以就會使用 .zip 格式。而且,公證服務需要能夠掃描一個可定義的檔案。這是一個讓你重新檢視 App 的機會,不要因為遺留了任何東西而浪費時間。你可以確認 App 的授權、擴充、擴展、核心程式碼、開發團隊、憑證、配置文件等資訊。當你完成重新檢視後,點擊 Upload

Beyond the Sandbox: Signing and distributing macOS apps  outside of the Mac App Store 8

在下一個畫面當中,你將會看到一些關於和 Apple 伺服器交握 (handshaking)、準備上傳的訊息,以及上傳的進度。當 App Bundle 成功上傳到 Apple 伺服器之後,你將會看到這個畫面:

uploading-app

現在我們就要等待,等待的時間取決於兩個因素:Apple 伺服器忙碌的程度、以及你的 App 有多大,不過這個過程通常是幾分鐘就能夠完成。在印象中,我沒有試過要等待超過 5-7 分鐘,而且那是 Apple 首次在 Catalina 版本開始要求進行公證的期間,當時所有人都在急著讓 Apple 檢查他們的第三方 App:

app-successfully-notarized

完成了!現在點擊 Export…,並將檔案放在你選擇的資料夾之中。通常我會直接把它儲存在 /Applications 資料夾之中,因為我實際上是在「安裝」一個已經準備好的 App。如果我在 /Applications 中雙擊一個剛過公證的 App,App 就會立即運行,因為它已經經過公證,Apple 的 Gatekeeper 機制會監控它並讓它執行。不過這並不是發佈 App 的方式,我們還需要創建一個安裝檔

創建一個安裝檔來發佈 App

關於創建安裝檔的詳細步驟,其實已經超出了這篇教學的範疇。話雖如此,我其實也在準備在 Appcoda 寫下一篇文章,詳細教你如何使用免費軟件 Packages 在 Mac 上創建軟件安裝檔,我相信在 Mac 平台上創建安裝檔,最好的 App 就是 Packages 了。(聲明:我與 Packages App 作者 Stéphane Sudre 沒有任何的個人或利益關係,只是單純地鼓勵你使用這個 App,以支持作者的努力。)

要開始學習如何透過 Packages 建立安裝檔,我們首先要下載軟件、讀讀關於它的資料、試試它的功能、開啟一個新的專案、查看相關資源和技術規格文件、並閱讀一些教學文章。請記住,我將會在本系列教學文章的第三部分中,展示如何使用 Packages 為我們今天討論的 App 建立安裝檔。

這裡有一個關於後續 Packages 教學文章的小提示,你的安裝檔需要一個 “tag”,也可以叫做 “identifier”,就像是 App 的 Bundle Identifier。以我的範例來說,就使用了 us.microit.pkg.AppNotaryAndDistrib。你可以注意到,它是以我公司網站的域名反向作為開頭所組成的,就像 App 的 Bundle ID 一樣。

我創建了一個 Packages 專案,來執行可發佈軟件的 .pkg 安裝檔。讓我們簡單看一下如何將範例 App Bundle AppNotaryAndDistrib.app 加入到 Packages 的專案裡面:

Packages 專案經過設定並建置之後,現在我有了一個名為 AppNotaryAndDistrib.pkg 的功能齊全安裝檔。請記住,我不能發佈這個安裝檔,因為它沒有經過簽署與公證,這樣的話,Apple 的 Gatekeeper 會告知使用者此安裝檔可能含有惡意內容,而且來源是未知的開發者。那我們應該怎麼做?我們需要簽署並公證安裝檔。這個流程不簡單,讓我們逐步看看吧。

簽署安裝檔

你們應該都知道,安裝檔需要以有效的憑證來進行簽署。安裝檔是一個用來將一個 App 安裝在某台 Mac 上的 App,而我們不希望任何人對它進行竄改。讓我們使用前文提過的 Developer ID 憑證,在 Terminal 透過 productsign 命令簽署安裝檔,並檢查輸出。命令的格式為:

productsign --sign "Developer ID Installer: TEAM_NAME (TEAM_ID)" "ORIGINAL_INSTALLER_NAME" "SIGNED_INSTALLER_NAME"

讓我們使用真實的參數來執行它,像是我的公司名稱 (TEAM_NAME)、檔案名稱等,唯獨是我的 TEAM_ID,我會將它變更為 “ABCABCABCD”:

productsign --sign "Developer ID Installer: microIT Infrastructure, LLC (ABCABCABCD)" "AppNotaryAndDistrib.pkg" "AppNotaryAndDistrib_1.0_Installer.pkg"

以下是執行命令後產生的輸出:

productsign: using timestamp authority for signature
productsign: signing product with identity "Developer ID Installer: microIT Infrastructure, LLC (ABCABCABCD)" from keychain /Users/andrewjaffee/Library/Keychains/login.keychain-db
productsign: adding certificate "Developer ID Certification Authority"
productsign: adding certificate "Apple Root CA"
productsign: Wrote signed product archive to AppNotaryAndDistrib_1.0_Installer.pkg

看看到輸出的最後一行中,有一個新的檔案,那就是經過簽署的安裝檔 AppNotaryAndDistrib_1.0_Installer.pkg,它會被存放在你執行 productsign 的資料夾中。但我們現在還不能使用這個安裝檔,因為它還沒經過公證。你準備好迎接後續艱澀的步驟了嗎?

公證安裝檔

經過前面的討論,你已經瞭解為什麼我們需要公證安裝檔,不過你可能還不瞭解如何進行公證。壞消息是 Apple 並沒有簡化這個過程,這全部的流程都需要在終端機中進行,而且非常繁瑣。重要提醒:你會需要使用 Apple ID,以及安裝檔的 Bundle ID,也就是前面提到的 us.microit.pkg.AppNotaryAndDistrib。如果你有使用 Apple ID 的雙重驗證功能,你也會需要使用 App 專用密碼,如果你不想將 Apple ID 及密碼以 clear text 的方式傳送,也可以使用 Keychain placeholders

打開一個 Terminal 視窗,並跟著下列步驟來輸入指令,並確認輸出結果。我會在某些命令的參數中使用佔位符,以隱藏我的私人資訊。我們將由上傳安裝檔給 Apple 開始:

xcrun altool --notarize-app --primary-bundle-id "us.microit.pkg.AppNotaryAndDistrib" --username "[email protected]" --password "PASSWORD" --file AppNotaryAndDistrib_1.0_Installer.pkg

因為需要時間將安裝檔上傳,Terminal 將會停頓一會兒,不過完成後就馬上會產生下列輸出結果:

No errors uploading 'AppNotaryAndDistrib_1.0_Installer.pkg'.
RequestUUID = cadc5ae2-768a-4cee-8719-f977c422b1c6

記得保留 RequestUUID 的資訊,因為之後我們會使用它來確認及追蹤安裝檔的公證進度。你會在 Apple ID 收到一封電郵,在等待電郵的同時,我們可以繼續進行 Terminal 的流程。幾分鐘後,你可以執行這個指令:

xcrun altool --notarization-history 0 -u "[email protected]" -p "PASSWORD"

它會馬上回傳一個關於公證結果的紀錄,這個列表包含了你提交的所有檔案及其相應狀態。你會從裡面找到有剛剛 RequestUUID 的項目,它應該會在清單的頂端:

Notarization History - page 0

Date                      RequestUUID                          Status  Status Code Status Message
------------------------- ------------------------------------ ------- ----------- ----------------
2020-05-24 19:34:46 +0000 cadc5ae2-768a-4cee-8719-f977c422b1c6 success 0           Package Approved
2020-05-22 05:20:00 +0000 a7b855f8-986c-4df0-a938-24876c588b27 success 0           Package Approved

Next page value: 1590124800000

沒錯,第一行的項目資訊與我的 RequestUUID 符合,後面的狀態顯示為 “Package Approved”。而第二行是使用 Xcode 進行 App 公證的資訊,這部分在本篇教學前面的部分已經展示過。

你的安裝檔已經差不多準備好了。還有一點要注意的是,假如 Apple 還沒完成你的安裝檔公證流程,就會顯示你的請求還在等待處理中。你可以繼續執行最後一條指令,來確認公證狀態是成功還是失敗。如果公證失敗該怎麼辦?我們能夠找出原因嗎?

你可以藉由 JSON 報告來瞭解公證狀態的詳細資訊。讓我們來試試看吧!只需要兩個步驟,首先,配合安裝檔的 RequestUUID,將這個指令輸入到 Terminal 中:

xcrun altool --notarization-info cadc5ae2-768a-4cee-8719-f977c422b1c6 -u "[email protected]" -p "PASSWORD"

你將會收到以下資訊:

No errors getting notarization info.

          Date: 2020-05-24 19:34:46 +0000
          Hash: 3a5ecc35c373ad872718c8c2c7a4efc21ac5ac3b2739c5e4bef995e910fcf851
    LogFileURL: https://osxapps-ssl.itunes.apple.com/itunes-assets/Enigma123/v4/d2/94/27/d2942733-d44b-5533-fae9-8bbf78d840ba/developer_log.json?accessKey=1590622884_2683968192308681510_zBw4%2BSVyZ%2Fwcy1nlvnkT%2Bo7LVAefv5uDiMG6cz80lAdMrL4mIBCUnhX37utPeGclAZ66U90RdNvhggbBlRF3tuVDJN13uOU3rrSTkLngKRiMDDW3bYcaiSZ2tMqzYBMWykmp%2Fcrs435%2ByIIWmW9E798Ql3Bd1yLBo%2FFDwxeBn8c%3D
   RequestUUID: cadc5ae2-768a-4cee-8719-f977c422b1c6
        Status: success
   Status Code: 0
Status Message: Package Approved

讓我們看看 StatusStatus Code、 和 Status Message 欄位的資訊,如我們所知,我的安裝檔已經公證成功 (Package Approved)。假如這幾個欄位不是 success0、 和Package Approved,你可以嘗試使用瀏覽器連結到 LogFileURL 來找出公證失敗的原因。先不要抱有太多期待,Apple 對於安裝檔的自動檢查做得不是太好,但這已經是你能夠獲得的所有資訊了,它有時候真的能夠幫你找到一些明顯的錯誤。

第二步是獲得公證詳細資訊最重要的步驟,就我們的情況而言,連結到 LogFileURL 會很有趣,但查看回傳的 JSON 內容更有幫助,讓我們可以看一下它的結構。我用 Safari 連結到 LogFileURL 並獲得下列內容:

{
  "logFormatVersion": 1,
  "jobId": "cadc5ae2-768a-4cee-8719-f977c422b1c6",
  "status": "Accepted",
  "statusSummary": "Ready for distribution",
  "statusCode": 0,
  "archiveFilename": "AppNotaryAndDistrib_1.0_Installer.pkg",
  "uploadDate": "2020-05-24T19:34:46Z",
  "sha256": "3a5ecc35c373ad872718c8c2c7a4efc21ac5ac3b2739c5e4bef995e910fcf851",
  "ticketContents": [
    {
      "path": "AppNotaryAndDistrib_1.0_Installer.pkg",
      "digestAlgorithm": "SHA-1",
      "cdhash": "72e859f50fddcd045091a2bb4ccd8d0bba94633b"
    }
  ],
  "issues": [
    {
      "severity": "warning",
      "code": null,
      "path": "AppNotaryAndDistrib_1.0_Installer.pkg",
      "message": "This archive is corrupt, and cannot be unpacked for analysis.",
      "docUrl": null,
      "architecture": null
    }
  ]
}

你現在看到的是,Apple 嘗試盤點你所提交的資訊,並檢查裡面是否包含惡意內容。我剛剛說這「很有趣」,是因為 status 顯示為 “Accepted”,而 statusSummary 為 “Ready for distribution”,但 issues 卻顯示 “This archive is corrupt, and cannot be unpacked for analysis”,但這只是個警告訊息,實際上安裝檔並沒有損毀,因為我已經測試了許多次,它是可以正常運作的。我相信 Apple 會認為此檔案 “cannot be unpacked for analysis” 是因為我的安裝檔已經使用了有效的憑證進行簽署,而我並不希望任何人竄改它。在最後,請注意 ticketContents 的欄位資訊,這跟「裝訂 (stapling)」程序有關,我們馬上就會討論到這一部分。

裝訂安裝檔

現在你的安裝檔已經完成了公證,你可以將它發佈給數百萬的客戶對吧?當你的客戶下載並執行安裝檔後,Apple 的 Gatekeeper 機制會透過網路來允許安裝檔繼續執行。但是,如果因為某些原因,客戶在執行安裝檔的時候網路斷線怎麼辦?如果沒辦法連線到 Apple 伺服器進行驗證,Gatekeeper 機制就不會允許安裝檔繼續執行。為了應對這種情況,Apple 允許你「裝訂」安裝檔的「令牌」,如此一來,無論網路是否在連接的狀態,它都可以順利執行:

xcrun stapler staple "AppNotaryAndDistrib_1.0_Installer.pkg"

以下是裝訂程式所告訴我們的資訊:

Processing: /Users/andrewjaffee/Documents/AppNotaryAndDistrib_1.0_Installer.pkg
Processing: /Users/andrewjaffee/Documents/AppNotaryAndDistrib_1.0_Installer.pkg
The staple and validate action worked!

我們終於獲得了一個安裝檔。還記得前面我曾經測試將範例 App 拖拉到 /Applications 中進行安裝嗎?現在我將它刪除,並重新使用新的安裝檔來安裝,看看會發生什麼事:

installation-successful

當我查看 /ApplicationsAppNotaryAndDistrib.app 已經成功安裝了。我雙擊 App 圖示,它可以順利執行,也沒有跳出任何關於惡意軟件的警告訊息。

你可以將安裝檔放置到任何網站上,利用廣告來推銷並銷售它,而整個行銷流程都由你所控制。如此一來,你就可以獲得最大的控制權和利潤,你也可以透過第三方來銷售 App,但這樣可能會讓利潤減少。不過,這裡最大的優點就是你可以完全控制自己的 App

全部任務都完成了!

總結

到底 Apple 的公證流程真的是為了保護客戶,不受惡意軟件的攻擊,還是只是想要強迫全部 OS X App 都上架到 Mac App Store 之中,以便這家市值數億美元的公司能夠向大家收取高額費用?我的看法是兩種原因都有,因為 Apple 已經完全控制了 iOS 的生態系統。

駭客攻擊、身份盜用、有意或無意的惡意軟件攻擊,肯定是巨大而且日趨嚴重的問題。保護使用者免受這些攻擊是個崇高的理想,所有開發者在開發程式碼時都應該緊記使用者的安全。另一方面,開放市場與開源軟件也為世界帶來龐大的財富與知識。

我希望我們可以找到一個快樂的媒介,也希望 Apple 可以繼續將 macOS 生態系統允許第三方 App 的存在。此教學系列文章還有第二和第三部分,記得不要錯過!

譯者簡介:HengJay,iOS 初學者,閒暇之餘習慣透過線上 MOOC 資源學習新的技術,喜歡 Swift 平易近人的語法也喜歡狗狗,目前參與生醫領域相關應用的 App 開發,希望分享文章的同時也能持續精進自己的基礎。

LinkedIn: https://www.linkedin.com/in/hengjiewang/
Facebook: https://www.facebook.com/hengjie.wang

原文Beyond the Sandbox: Signing and distributing macOS apps outside of the Mac App Store

作者
Andrew Jaffee
熱愛寫作的多產作家,亦是軟體工程師、設計師、和開發員。最近專注於 Swift 的 iOS 手機 App 開發。但對於 C#、C++、.NET、JavaScript、HTML、CSS、jQuery、SQL Server、MySQL、Agile、Test Driven Development、Git、Continuous Integration、Responsive Web Design 等。
評論
更多來自 AppCoda 中文版
很好! 你已成功註冊。
歡迎回來! 你已成功登入。
你已成功訂閱 AppCoda 中文版 電子報。
你的連結已失效。
成功! 請檢查你的電子郵件以獲取用於登入的連結。
好! 你的付費資料已更新。
你的付費方式並未更新。