如何在使用 WiX 安装期间加密 app.config 文件部分?

发布于 2024-07-09 02:28:28 字数 302 浏览 11 评论 0原文

我找到了一个在安装过程中加密 web.config 的示例 这里,但我的应用程序是Windows服务。 aspnetreg_iis 方法仅适用于 web.config 文件。

我知道如何以编程方式加密配置文件,但我认为我无法使用 WiX 做到这一点。 我错了吗? 有任何想法吗?

I have found an example for encrypting a web.config during installation here, but my app is a windows service. The aspnetreg_iis method works only for web.config files.

I know how to programatically encrypt the config file, but I don't think I can do that using WiX. Am I wrong? Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无畏 2024-07-16 02:28:28

这就是我最终的结果...

我使用 WiX 和 DTF 创建了一个托管代码自定义操作来加密配置文件的给定部分:

    public static void EncryptConfig(Session session)
    {

        var configPath = session["APPCONFIGPATH"];
        var sectionToEncrypt = session["SECTIONTOENCRYPT"];

        var fileMap = new ExeConfigurationFileMap();
        fileMap.ExeConfigFilename = configPath;
        var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
        ConfigurationSection section = configuration.GetSection(sectionToEncrypt);
       
        if (!section.SectionInformation.IsProtected)
        {
            section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
            section.SectionInformation.ForceSave = true;
            configuration.Save(ConfigurationSaveMode.Modified);

        }
    }

我缺乏理解,导致这个问题的部分原因是不知道您可以安全地创建使用 DTF 在托管代码中自定义操作。 DTF 上的文档很少,但是一旦你让它工作起来,那就太棒了。

我发现只有当我在 InstallFinalize 之后安排自定义操作时,这才有效。

这是实现这一目标的 WiX 配置:

<InstallExecuteSequence>
  <Custom Action="EncryptConfigurationFiles" After="InstallFinalize" />
</InstallExecuteSequence>

<Fragment>
    <Binary Id="YourProject.CustomActions.dll" SourceFile="$(var.YourProject.CustomActions.TargetDir)$(var.YourProject.CustomActions.TargetName).CA.dll" />
    <CustomAction Id="EncryptConfigurationFiles" BinaryKey="YourProject.CustomActions.dll" DllEntry="EncryptConfig" Return="check" />
</Fragment>

这些博客/网站帮助我实现了这一目标,上面的大部分代码都源自它们:

http://geekswithblogs.net/afeng/Default.aspx
http: //blog.torresdal.net/2008/10/24/WiXAndDTFUsingACustomActionToListAvailableWebSitesOnIIS.aspx
http://blogs.msdn.com/jasongin/archive/2008/07 /09/votive-project-platform-configurations.aspx

@PITADeveloper...感谢您的回复。 我发现我不需要加载程序集来加密配置文件。

如果你使用这个,你应该使用 try catch 并返回一个 ActionResult...上面是伪代码。

最后,我使用 DataProtectionConfigurationProvider。 对于 RSA 提供商,我认为还有一些障碍需要克服。

我希望这可以帮助别人!

Here is what I ended up with...

I used WiX and DTF to created a managed code Custom Action to encrypt a given section of a config file:

    public static void EncryptConfig(Session session)
    {

        var configPath = session["APPCONFIGPATH"];
        var sectionToEncrypt = session["SECTIONTOENCRYPT"];

        var fileMap = new ExeConfigurationFileMap();
        fileMap.ExeConfigFilename = configPath;
        var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
        ConfigurationSection section = configuration.GetSection(sectionToEncrypt);
       
        if (!section.SectionInformation.IsProtected)
        {
            section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
            section.SectionInformation.ForceSave = true;
            configuration.Save(ConfigurationSaveMode.Modified);

        }
    }

Part of my lack of understanding that prompted this question was not knowing that you can safely create custom actions in managed code using DTF. Documentation is sparse on DTF, but once you get it working, it is great.

I found that this only worked if I scheduled the custom action after InstallFinalize.

Here is the WiX config to make it happen:

<InstallExecuteSequence>
  <Custom Action="EncryptConfigurationFiles" After="InstallFinalize" />
</InstallExecuteSequence>

<Fragment>
    <Binary Id="YourProject.CustomActions.dll" SourceFile="$(var.YourProject.CustomActions.TargetDir)$(var.YourProject.CustomActions.TargetName).CA.dll" />
    <CustomAction Id="EncryptConfigurationFiles" BinaryKey="YourProject.CustomActions.dll" DllEntry="EncryptConfig" Return="check" />
</Fragment>

These blogs/sites helped me get there and much of the code from above was derived from them:

http://geekswithblogs.net/afeng/Default.aspx
http://blog.torresdal.net/2008/10/24/WiXAndDTFUsingACustomActionToListAvailableWebSitesOnIIS.aspx
http://blogs.msdn.com/jasongin/archive/2008/07/09/votive-project-platform-configurations.aspx

@PITADeveloper... Thanks for the response. I found that I did not need to load the assembly to encrypt the config file.

If you use this, you should use a try catch and return an ActionResult... The above is pseudo-code.

Finally, I'm using the DataProtectionConfigurationProvider. For the RSA Provider, I think there are a couple more hoops to jump through.

I hope this helps someone!

〆一缕阳光ご 2024-07-16 02:28:28

您应该能够在自定义操作中完成此操作。 我发现的问题是加载 ExeConfigurationFileMap 的程序集会引发异常,但您可以通过向 AppDomain 添加 AssemblyResolve 处理程序来处理该异常。 这是我编写的富客户端应用程序的一种破解,用于使用机器加密密钥加密/解密受保护的配置部分。 这可能不是最漂亮的代码,但我希望您能从中得到启发。 此代码假设您在配置文件中定义了要使用的 ProtectionProvider。

//class global
static System.Reflection.Assembly DefiningAssembly;

AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);

static System.Reflection.Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
     return DefiningAssembly;
}

然后,您可以像这样加载您的配置:

DefiningAssembly = System.Reflection.Assembly.LoadFrom("path to defining assembly for config");

//Set the Configuration using an ExeConfigurationFileMap - This works for any .config file.
ExeConfigurationFileMap CfgMap = new ExeConfigurationFileMap();
CfgMap.ExeConfigFilename = "path to config file";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(CfgMap, ConfigurationUserLevel.None);

List<string> DefiningAssemblyTypes = new List<string>();
foreach (System.Type type in DefiningAssembly.GetExportedTypes())
{
     DefiningAssemblyTypes.Add(type.Name);
}

foreach (ConfigurationSection tempSection in config.Sections)
{
     if (DefiningAssemblyTypes.Contains(tempSection.ElementInformation.Type.Name))
     {
          section = tempSection;
          break;
     }
}
ProtectionProviderName = section.SectionInformation.ProtectionProvider.Name;
section.SectionInformation.ProtectSection(ProtectionProviderName);
config.Save(ConfigurationSaveMode.Minimal, true);

我希望这对您有帮助,祝您好运。

You should be able to do it within a custom action. The catch that I've found is that loading an assembly for an ExeConfigurationFileMap will throw an exception, but you can handle that by adding an AssemblyResolve handler to the AppDomain. This is kind of a hack-up from a rich-client app I wrote to encrypt/decrypt protected configuration sections using a machine encryption key. It's probably not the prettiest code, but I'm hoping you can get the picture from it. This code assumes that you have the ProtectionProvider you want to use defined in the config file.

//class global
static System.Reflection.Assembly DefiningAssembly;

AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);

static System.Reflection.Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
     return DefiningAssembly;
}

Then, you can load your configuration like this:

DefiningAssembly = System.Reflection.Assembly.LoadFrom("path to defining assembly for config");

//Set the Configuration using an ExeConfigurationFileMap - This works for any .config file.
ExeConfigurationFileMap CfgMap = new ExeConfigurationFileMap();
CfgMap.ExeConfigFilename = "path to config file";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(CfgMap, ConfigurationUserLevel.None);

List<string> DefiningAssemblyTypes = new List<string>();
foreach (System.Type type in DefiningAssembly.GetExportedTypes())
{
     DefiningAssemblyTypes.Add(type.Name);
}

foreach (ConfigurationSection tempSection in config.Sections)
{
     if (DefiningAssemblyTypes.Contains(tempSection.ElementInformation.Type.Name))
     {
          section = tempSection;
          break;
     }
}
ProtectionProviderName = section.SectionInformation.ProtectionProvider.Name;
section.SectionInformation.ProtectSection(ProtectionProviderName);
config.Save(ConfigurationSaveMode.Minimal, true);

I hope this helps you, best of luck.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文