【问题标题】:How to Protect My Configuration File如何保护我的配置文件
【发布时间】:2017-03-22 17:22:06
【问题描述】:

我正在用 Visual Studio 构建的 C# 编写 SQL Server 应用程序。它是一个 Windows 窗体应用程序。该程序将安装在用户将运行它的网络上。

我正在努力解决的问题是如何管理配置文件。它有服务器用户名和密码供所有人查看。我尝试了 Click Once 和加密方案,但它们都要求程序在运行程序的计算机上运行。当我尝试从工作站运行它时它失败了。这与How do I avoid having the database password stored in plaintext in sourcecode? 不同,因为所有这些解决方案都建议使用集成安全或基于机器的加密。这些选项都不适合我。

任何帮助将不胜感激。

【问题讨论】:

  • 不要使用 SQL 授权。为数据库使用 Windows 凭据。
  • 编写一个客户端-服务器代码,其中服务器的代码不能被您的客户端访问,他们只能调用您的服务器方法...
  • 我不能使用 Windows 凭据 :( 我希望可以。
  • @FredrikLundvall 这是一个糟糕的主意!即使代码编译后,也可以反编译,你可以找到原始字符串。

标签: c# sql-server visual-studio configuration


【解决方案1】:

不要以纯文本形式存储密码。时期。句号。

您应该从 SQL Server 中获得启发。是的,您可以在 web/app.config 中以纯文本形式将用户名存储在密码中。但是对于生产服务器,您永远不应该这样做。相反,对于生产部署,您应该有一个使用集成安全性的配置。这允许通过访问由 Windows 安全处理而不是在配置文件中不安全处理的凭据来提升访问权限。

同样,您应该使用WindowsIdentityOpenId 之类的名称。然后,您可以在代码中传递身份验证令牌,而不是以纯文本形式存储凭据。

【讨论】:

    【解决方案2】:

    这就是软件开发人员创建包含中间件服务(如 Web 服务)的多层设计的原因。 Web 服务可以托管在 IIS 中,Windows 帐户和密码可以配置到应用程序连接池的应用程序标识部分。然后可以使用trusted_connection=true 配置web.config 连接字符串。以这种方式配置它会使用 Windows 数据保护 API 来保护身份。

    【讨论】:

      【解决方案3】:

      如果您指的是app.config 的数据,那很简单!你必须使用这两个类:

      EntityConnectionStringBuilder
      

      https://msdn.microsoft.com/en-us/library/system.data.entityclient.entityconnectionstringbuilder(v=vs.110).aspx

      SqlConnectionStringBuilder
      

      https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnectionstringbuilder(v=vs.110).aspx

      我从这个页面学习它:Programmatic Connection Strings in Entity Framework 6 这是非常好的指南。无论如何,该链接对您没有帮助!?只是谷歌这样的东西:

      C#在运行时定义连接字符串

      将所有连接字符串放入代码后,您可以从app.config 文件的connectionStrings 标记中删除任何敏感数据,因为您的应用将不再使用它!然后再次编译你的代码。

      如果您在 EF 中使用 DB First,那么您也可以查看本指南:How to set Connection String with Entity Framework

      更新:

      我添加了两个我管理的类,并用它们以编程方式(动态)创建连接字符串,一个属于我使用的实体框架项目SQL Server Compact Edition(SQL Server CE),第二个属于另一个实体我使用带有 SQL Server 身份验证的 SQL Server Express 2014 的框架项目(使用 sa 用户名)。如果有人需要,我将把这两种方法都留在这里:

      这属于我的 SQL Server CE 项目:

      public static string GetDBConnectionString(string dataParentPath = "")
      {
          EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
          SqlCeConnectionStringBuilder sqlCEBuilder = new SqlCeConnectionStringBuilder();
      
          if (string.IsNullOrEmpty(dataParentPath) == true)
              dataParentPath = @"C:\MyDBFolder\CMS.sdf";
      
          sqlCEBuilder.DataSource = dataParentPath;
          sqlCEBuilder.Password = "12345687";
          sqlCEBuilder.MaxDatabaseSize = 4090;
      
          entityBuilder.Metadata = "res://*/CMS.csdl|res://*/CMS.ssdl|res://*/CMS.msl";
          entityBuilder.ProviderConnectionString = sqlCEBuilder.ToString();
          entityBuilder.Provider = "System.Data.SqlServerCe.4.0";
      
          return entityBuilder.ToString();
      }
      

      这属于我的带有 SQL Server 身份验证的 SQL Server Express 项目:

      using System;
      using System.Collections.Generic;
      using System.Data.Entity.Core.EntityClient;
      using System.Data.SqlClient;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      
      namespace CMS
      {
          class mySettings
          {
              public static string GetDBConnectionString()
              {
                  // **************************************************
                  // This is my "ConnectionString" from App.config file.
                  // <connectionStrings>
                  //      <add name="CMSEntities" 
                  //          connectionString=
                  //              "metadata=res://*/CMS.csdl|res://*/CMS.ssdl|res://*/CMS.msl
                  //                  ;provider=System.Data.SqlClient
                  //                  ;provider connection string=&quot
                  //                  ;data source=MY-PC\SQLEXPRESS
                  //                  ;initial catalog=CMS
                  //                  ;user id=sa
                  //                  ;password=12345687
                  //                  ;MultipleActiveResultSets=True
                  //                  ;App=EntityFramework
                  //              &quot;"
                  //      providerName="System.Data.EntityClient" />
                  //</connectionStrings>
                  // **************************************************
      
                  string metaData = "res://*/CMS.csdl|res://*/CMS.ssdl|res://*/CMS.msl";
                  string providerName = "System.Data.SqlClient";
      
                  string dataSource = @"MY-PC\SQLEXPRESS";
                  string databaseName = "CMS"; // = InitialCatalog
                  string userID = "sa";
                  string password = "12345687";
                  string appName = "EntityFramework";
      
                  EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
                  SqlConnectionStringBuilder sqlBuilder = new SqlConnectionStringBuilder();
      
                  // = = = = = = = = = = = = = = = =
                  sqlBuilder.DataSource = dataSource;
                  sqlBuilder.InitialCatalog = databaseName;
                  sqlBuilder.MultipleActiveResultSets = true;
                  sqlBuilder.UserID = userID;
                  sqlBuilder.Password = password;
                  sqlBuilder.ApplicationName = appName;
      
      
                  // = = = = = = = = = = = = = = = =
                  entityBuilder.Provider = providerName;
                  entityBuilder.Metadata = metaData;
                  entityBuilder.ProviderConnectionString = sqlBuilder.ConnectionString;
      
                  return entityBuilder.ToString();
              }
          }
      }
      

      如您所见,我在两个项目中的数据库具有相同的名称“CMS”,因此其实体将命名为“CMSEntities”。现在! 你必须重写它的DbContext 构造函数。这是重要但最简单的部分!比我更好的描述来自这个页面“http://www.cosairus.com/Blog/2015/3/10/programmatic-connection-strings-in-entity-framework-6”:

      现在您的实体模型从 DbContext 扩展而来,而 DbContext 提供了一个 构造函数传入连接字符串,但您的实体模型确实如此 不要为您重载那些构造函数。为了访问 构造函数重载,您将需要为 您的实体模型数据库上下文与您在同一命名空间中 具有所需构造函数签名的实体模型。专业提示:一定要 将 cs 文件的文件名命名为与实体不同的名称 在未来生成的代码发生的情况下建模数据库上下文 不要覆盖您的更改。

      所以我在我的项目的 root 建立了一个类,该类必须是partial:

      using System;
      using System.Collections.Generic;
      using System.Data.Entity;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      
      namespace CMS  // Your Project Namespace
      {
          public partial class CMSEntities : DbContext
          {
              public CMSEntities(string connectionString)
                  : base(connectionString)
              {
              }
          }
      }
      

      每当我想访问我的数据库时,我都会使用此代码:

          using (CMSEntities db = new CMSEntities(CMSSettings.GetDBConnectionString()))
          {
              // Do your DB stuff here...
          }
      

      我希望它能帮助你或其他我从这个网站“stackoverflow”和用户那里学到的所有东西。

      祝你好运

      【讨论】:

      • 不,这种方法只会在运行时使用(调试,发布)。您可以尝试一下,如果您需要更多信息,可以查看Programmatic connection strings in entity framework 6 正如我提到的,我在我的两个项目中使用它没有问题。我也在我的代码中加密了我的密码!!大声笑如果你愿意,你可以这样做以提高安全性!
      • 顺便说一句,欢迎您!我只是从这个网站和其他网站上学到了所有这些,我很乐意重新分享。我希望这些方法也对您有所帮助,如果确实如此,请将其标记为答案。谢谢。
      • 哦!为什么要按回车发帖!!!没有编辑!?!正如这里所说:social.msdn.microsoft.com/Forums/en-US/… 黑客可以在解密后从内存中检索加密数据以在应用程序中使用,所以除非你在做 NSA 级别,否则你需要的不仅仅是这些方法!!?
      • @MRK 您可以构建应用程序,这样您就不必授予用户数据库权限。阅读 LB 对这个问题的评论。
      • @mason ,我无法在 Michael Keleher 帖子下发表评论,并请他给我们一个链接,指向有关他谈论方式的指南或教程。 (我矮了 39 点!哈哈)你能给我一个链接从它开始吗!?感谢高级
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-22
      • 1970-01-01
      • 1970-01-01
      • 2021-06-24
      • 2016-08-17
      • 2017-03-29
      • 1970-01-01
      相关资源
      最近更新 更多