原文链接 (自备梯子)
一些可以保护 API key 等信息的简单方法
几乎所有 iOS 应用都需要使用一些私有值, 比如 API key,HMAC secrets 或密码有一个简单的途径可以把这些私有值包含到你的 app 中, 那就是把它们写在代码里或者写在 Info.plist 文件里但是这么做会产生一个问题, 就是这些文件会被包含到 Git 仓库里, 任何人都可以看到并获取到源代码, 自然也就可以获取到这些敏感信息
保护源代码
针对上面提及的问题, 首先想到的解决方式可能很简单, 就是直接保护源代码, 这样其他人就没法获取到源码, 也就没办法获取到这些敏感信息了然而不幸的是很多应用是开源的, 每个人都需要去获取其源码, 所以这种解决方式并不总是奏效的对于一些顶级的 iOS app, 人们还可以去反编译它或者分析应用包的 Contents 来寻找这些敏感信息
让文件不包含到 Git 仓库中
在允许保持代码开源的前提下, 你可以简单地让包含敏感信息的文件被 Git 忽略任何人需要在项目中使用这些敏感信息, 可以简单地创建相关文件对于一个开源项目来说, 这些相关细节, 可以在 README 或者 wiki 页面里注明
如果按照上面所说, 那么一个 iOS 应用, 每一个开发者都需要创建一个源代码文件或者一个 plist 文件, 然后添加到项目中这样你不得不很小心地在项目设置里去确保相关文件的引用情况, 即使当这些相关文件不包含在 Git 中
xcconfig
我更倾向于把敏感信息保存在 xcconfig 文件中, 每一个编译环境 ( Debug 或 Release ) 对应一个文件这些文件可以让你在不同环境使用不同的配置, 为开发者简化配置, 而且让敏感信息不包含在 Git 仓库里
1. 创建一些样例文件在项目里
我更喜欢把它们放在 BuildConfig 文件夹里, 让它们与项目里的其他文件分离开开发者只需要简单地复制它们, 给它们重命名, 然后把一些敏感信息写到里面这些样例文件可以指定 key 的列表, 但是不把值包含进去每一个编译版本的配置, 比如 Debug 和 Release, 都需要这么一个文件
- debug.example.xccconfig
- API_CLIENT_ID = API_CLIENT_ID_FOR_TEST
- API_CLIENT_SECRET = API_CLIENT_SECRET_FOR_TEST
- release.example.xccconfig
- API_CLIENT_ID = API_CLIENT_ID_FOR_PRODUCTION
- API_CLIENT_SECRET = API_CLIENT_SECRET_FOR_PRODUCTION
你将需要把这些文件添加到 Xcode 项目中但是你要确定把他们从 Xcode 的文件检查器的 Target Membership 区域中移除
2. 为每一个编译版本创建真实文件
在这里面把例子的值替换成项目里真实的值
- debug.example.xccconfig
- API_CLIENT_ID = 123456789
- API_CLIENT_SECRET = abcdefgh
- release.example.xccconfig
- API_CLIENT_ID = 987654321
- API_CLIENT_SECRET = hgfedcba
你将要把这些文件添加到项目中, 但是它们不需要依附到任何 target
3. 把这些配置文件添加到 .gitignore 文件中
4. 在项目设置里选中这些文件
你需要在
Info - >Configurations
中选中这些文件, 在 Debug 和 Release 中都去设置它们
值的使用
任何包含在 xcconfig 文件的值都可以作为项目文件的环境变量来使用, 比如 Info.plist, 如果需要再代码里使用这些值, 你需要在 Info.plist 创建一个属性链接到环境变量, 使用这种格式 $(API_CONFIG_KEY)
2018-02-01 更新
把敏感信息保存在 Info.plist 不是最安全的方式如果你的应该比较注重安全性, 那么你可能需要把这些敏感信息放在其他地方本篇文章的侧重点事把它们排除在 Git 仓库之外后面我会再更新说明如何在代码中使用这些环境变量, 来作为 Info.plist 的代替方案
2018-02-03 更新
使用 Sourcery, 可以生成一个 Swift 结构体, 该结构体包含了在 xcconfig 文件里的特定敏感信息
把 Sourcery 添加到项目中
创建一个 stencil 文件, 例如 AppSecrets.stencil, 把项目代码里需要访问到的敏感信息都写在这里, 作为 Swift 常量
- struct AppSecrets {
- static let secretKey = "{{ argument.secretKey }}"
- }
添加 build phase 来生成 AppSecrets.swift
Tools / Sourcery / bin / sourcery--sources Sources--templates Templates / AppSecrets.stencil--output Generated--args secretKey = \"$SECRET_KEY\""
Sourcery 的路径取决于是怎么安装它的, 我这例子里是作为一个独立版本工具, 将它包含在项目中
上面那个 sources 参数是必须的, 虽然在这种情况下并没有用到, 只是在后面输入了一个在项目里的有效路径
上面 templates 参数是 AppSecrets.stencil 相对于 root 的路径
output 文件夹是 AppSecrets.swift 写入的地方, 这个文件夹必须有你可以在 build phase 添加 mkdir -p Generated 来确保这个文件夹存在
写这些参数的时候, 他们分开的格式应该是这样: arg1=one,arg2=two 我避免在 SECRET_KEY 内容里添加任何特殊字符
把 AppSecrets.swift 加入到 .gitignore 文件中, 让它不被添加到 Git 仓库中
编译项目, 然后把 AppSecrets.swift 加到项目中, 这样 AppSecrets.swift 会被编译和链接到项目的 target 中
注意: 如果你的 App key 之类的敏感信息没有要求在不同的编译条件下( debug 和 release) 具有不同的值, 你可以跳过 xcconfig 部分你可以使用另一个方案, 那就是把敏感信息写成一个可执行的 shell 脚本, 添加到 build phase 中
总结一下, 通过以上这些方法, 你可以让你项目中的敏感信息不被加入到 Git 仓库里, 与此同时, 对于这个项目新的开发者们来说, 也比较易于理解上手
来源: https://juejin.im/post/5a7ae875f265da4e983efac7