使用代码生成为 Swift 项目提供轻松的 Secrets 管理。一种比 NSHipster 文章 中关于使用 Swift Build Tool Plugin (Swift 5.6+) 在 iOS 上进行 Secrets 管理所概述的 GYB 文件更简单的方法。
Secrets
提供便捷访问使用 .env
bash 脚本导出您希望在源代码中可用的 Secrets。
#prefix ORG
export ORG_API_CLIENT_SECRET=hrFL6LpsGQPsEQdipfTSlosI6topYTfhLNCfIvbfUz5r6nc72DMRbLL3msjuAFnY
export ORG_ANALYTICS_KEY=dak37Qv5KGwNsQxVJxjJY2OtbUnGKXlm3mkDApSRfrAsTHQdFRSEfrA9yin5T4YT
export ORG_BACKEND_KEY='KwphtrRhgOXcRd=p!73QnrQLuOj=rx8edJhMy52sWeQPKMxOxA8hNcDrG9=XRvAw'
export ORG_LOGGER_KEY='oW7YQKg2eNcVjzRdmCtmgCCSBp2dpJlL5NC-Pj!asS5XdPG/--R2hE?/=I/TlotP'
使用此插件,将生成以下 Swift 代码,并可直接用于您的目标源代码,无需导入。
// This file is automatically generated
import struct Foundation.Data
private func secret(_ secret: String) -> String {
let data = Data(base64Encoded: secret)
guard let data else {
fatalError("Failed to decode a secret!")
}
func decrypt(_ data: Data) -> String {
let key = Data(base64Encoded: "JbiOFqC+jH3l8pwCLE4Nca4f19M7YAbeTUo7rhnSSG7ctZMlc+dg5FI9o3zrSbCgFLtDd0uC9EcCC+jd6hlVDA==")!
var output: [UTF8.CodeUnit] = []
for (offset, ch) in data.enumerated() {
output.append(ch ^ key[offset % key.count])
}
return String(bytes: output, encoding: .utf8)!
}
return decrypt(data)
}
enum Secrets {
static let apiClientSecret = secret("TcrIWpby/A6io8xxaR9pGN55g4BXD3WXez5U3kCGLgaQ+9BDOpECggdHlg7dJ9OXJv8OJSnOuHRveIKoq187VQ==")
static let analyticsKey = secret("QdnlJZfv+kiutetMXx91J+RnvZliUkmqLx9V6VKKJAPv2PhhMpcztjRP4g+/AeHEUukQMi3wtX57Yobovi0MWA==")
static let backendKey = secret("bs/+ftTM3hWCvcRhfiowAY8o5IJVEleSOAVRk2uqcAu4//toCtJSlwVY8iygBMjvbPp7HwXhsDVFMtWFuG8Uew==")
static let loggerKey = secret("Su+5T/H160+AvP9URjRfFcNco75cI0WNDzoJymmYJCLp+9AII41BhSFuliSPGfePOZYRRSPHy2g/QseJhnYhXA==")
}
需要 Swift 5.6 (Xcode 13.3+)
在您的根目录(与 Package.swift
或您的 *.xcodeproj
并行)中创建一个 .env
文件。您可以使用 #prefix
定义要从所有导出的键中剥离的前缀。请参阅 用法 以获取 .env
文件示例。
SecretsManagerPlugin
添加到 Run Build Tool Plug-ins将以下内容添加到您的 Package.swift
文件依赖项数组中
.package(url: "https://github.com/vdka/SecretsManager.git", from: "1.0.0"),
并添加到 Secrets 应该可用的目标中,在其 dependencies
之后
plugins: [
.plugin(name: "SecretsManagerPlugin", package: "SecretsManager"),
]
在 Xcode Cloud 中运行时,您将希望 secret 值来自实际环境。为了告诉插件从哪个环境中读取键,您可以创建一个 .env
文件,该文件仅导出键,而不导出关联的值。
#prefix ORG
export ORG_API_CLIENT_SECRET
export ORG_ANALYTICS_KEY
export ORG_BACKEND_KEY
export ORG_LOGGER_KEY
此软件包的目的不是保护您的 Secrets 免受蓄意攻击。它的目的是使在 Swift 项目中方便地采用最佳实践 Secrets 管理。它通过确保将您的 secrets 保存在源代码之外不会牺牲可用性,并且在编译到您的应用程序中时,它们不会以明文形式存储来实现这一点。请记住 客户端保密是不可能的。