【问题标题】:Proper way to hide API keys in Git在 Git 中隐藏 API 密钥的正确方法
【发布时间】:2018-02-13 22:55:37
【问题描述】:

在我的 C# 项目中有 APIKeys.cs 文件,其中包含带有 API 密钥的 const 字符串。 我希望这些字符串在 Git 服务器中为空,但在我的本地计算机中有实际的 API 密钥。 所以拉项目的人可以毫无问题地编译它,而我的本地计算机仍然会在同一个文件中拥有 API 密钥。

如果我尝试上传带有空字符串的 APIKeys.cs 文件,那么我无法拥有带有 API 密钥的本地文件,因为当我尝试推送它时,它会覆盖空的 APIKeys.cs 文件。我也不能忽略这个文件,因为它会从 Git 服务器中删除空的 APIKeys.cs 文件。

那么对于这个问题,什么是最好的自动化方法,它允许在服务器中使用空字符串的类文件,所以当人们拉取它并在本地计算机中有真正的类文件时,项目将是可编译的?

【问题讨论】:

  • 不幸的是,没有自动的方法可以做到这一点(据我所知)。每次提交时,您可能只需要从暂存区域中删除文件。

标签: c# git api-key


【解决方案1】:

我现在想出了另一个不完美但对我来说仍然足够好的解决方案,例如:

APIKeys.cs文件:

public static partial class APIKeys
{
    public static readonly string ImgurClientID = "";
    public static readonly string ImgurClientSecret = "";
    public static readonly string GoogleClientID = "";
    public static readonly string GoogleClientSecret = "";
    public static readonly string PastebinKey = "";
    ...
}

APIKeysLocal.cs文件:

public static partial class APIKeys
{
    static APIKeys()
    {
        ImgurClientID = "1234567890";
        ImgurClientSecret = "1234567890";
        GoogleClientID = "1234567890";
        GoogleClientSecret = "1234567890";
        PastebinKey = "1234567890";
        ...
     }
}

忽略 Git 中的 APIKeysLocal.cs 文件,如果从解决方案资源管理器中删除此文件,没有此文件的人仍然可以编译项目。

如果APIKeysLocal.cs 文件尚不存在,我也会使用项目预构建事件自动创建它:

cd $(ProjectDir)APIKeys\

if not exist APIKeysLocal.cs (
    type nul > APIKeysLocal.cs
)

这样用户不需要做任何事情就可以编译项目。

【讨论】:

  • 我喜欢这个解决方案。一件事:当不需要编译时,为什么要创建一个空的APIKeysLocal.cs 文件?我对预构建事件知之甚少,但如果相反,它基于模板构建了一个本地文件,该模板在构造函数中也有空字符串供其他人填充,那么这将更有意义。然后其他人可以看到您的本地文件是如何设置并执行相同操作的。
【解决方案2】:

接受您不能在公共空间中隐藏未加密的私钥。

您可以做的是将密钥移动到私有空间,然后从代码中引用该私有空间。

您的私人空间可能是环境变量或 Windows 注册表,它应该是您应用源代码之外的东西。

另一种方法是创建一个新的配置文件(例如keys.config)专门用于存储私钥,然后将该文件从源代码管理中排除。

这意味着您不共享您的私钥,但这也意味着您需要记录(可能在 readme.md 中)用户需要重新创建自己的 keys.config。更好的(感谢@Joey)是在解决方案中包含一个示例配置文件(keys.sample.config),说明需要什么。

Here is an example

【讨论】:

  • 我通常使用配置文件方法并在源代码控制中包含一个foo.config.sample,然后可以将其复制到实际密钥或密码或开发人员特定设置所在的foo.config,并且也将被忽略通过源代码管理。
  • 一个空的keys.config是个坏主意,因为更改总是会再次进入源代码管理:-)。实际配置不应该被签入。
  • 我知道我不能隐藏密钥,但 API 服务所有者有规则不公开共享密钥,所以即使很容易反编译并在 C# 应用程序中看到它们,我仍然必须在 Git 中隐藏它们.我不认为在注册表中存储 30 个不同的上传器 api 密钥是个好主意。
  • 我现在检查了配置文件,当项目编译时,它会在可执行文件所在的位置创建配置文件,因此当人们使用安装程序时,API 密钥将很容易在该配置文件中可见,而某些 API 服务不允许这样做所有者。
【解决方案3】:

你有两个选择:

  1. 告诉 Git 忽略本地计算机上对 APIKeys.cs 的更改:

    git update-index --skip-worktree APIKeys.cs
    

    这将导致本地更改无法提交。如果您确实想要提交对文件的更改,则必须使用 --no-skip-worktree 标志撤消此操作。

  2. APIKeys.cs 文件重命名为APIKeys.template.cs 之类的名称,其中包含您要共享的空白字符串。将此文件保存在您的存储库中。将该文件复制到APIKeys.cs。将APIKeys.cs 添加到您的.gitignore。添加说明以复制模板文件并使用本地设置进行修改。

    git mv APIKeys.cs APIKeys.template.cs
    $EDITOR APIKeys.template.cs
    git commit
    cat APIKeys.cs >> .gitignore
    cp APIKeys.template.cs APIKeys.cs
    

【讨论】:

  • 我尝试了假设不变,它运行良好。当我拉动时,Git 不会用空的文件覆盖我的 api 密钥文件,我无法将我的 api 密钥推送到服务器以覆盖空文件,所以这正是我想要的。但是,如果一个开发人员忘记做假设不变,那么那个人可能会不小心按下 api 键,这是有问题的。但我认为我找不到比假设不变更好的解决方案。
  • @Jaex,是的,--assume-unchanged 确实存在风险。我建议的另一种方法是echoed by Ed GuinessJoey,实际上是我的首选方法。
【解决方案4】:

这不是非常类似于将内部版本号注入组件的问题吗?我这样做的方法是有一个预构建步骤,它根据一些环境变量生成一个名为 AssemblyVersionInfo.cs 的文件。你可以用你的 API 密钥做同样的事情。

在 API 密钥中编译的组件的预构建步骤中,输入如下内容:-

if not defined API_KEY set API_KEY=DEFAULT_KEY
echo public class ApiKeys>"$(SolutionDir)src\ApiKeys.cs"
echo {>>"$(SolutionDir)src\ApiKeys.cs"
echo public const string Key="%API_KEY%";>>"$(SolutionDir)src\ApiKeys.cs"
echo }>>"$(SolutionDir)src\ApiKeys.cs"

然后您在本地机器上设置用户或系统环境变量,其中包含真正的密钥。

setx API_KEY THE_REAL_KEY

为了避免 Git 想要提交文件,只需将其添加到 .gitignore。

【讨论】:

    猜你喜欢
    • 2021-04-30
    • 1970-01-01
    • 1970-01-01
    • 2017-03-12
    • 2021-01-27
    • 2019-01-07
    • 2020-04-15
    • 2020-05-12
    相关资源
    最近更新 更多