如何安全地配置数据库连接

相似但不一样:

  • 如何安全存储数据库连接详细信息
  • 安全地连接到应用程序中的数据库

大家好,我有一个连接到数据库服务器的C#WinForms应用程序。 数据库连接字符串(包括通用用户/传递)放在NHibernate配置文件中,该文件与exe文件位于同一目录中。

现在我遇到了这个问题:运行应用程序的用户不应该知道普通数据库用户的用户名/密码,因为我不希望他直接在数据库中搜索。

或者,我可以对连接字符串进行硬编码,这是不好的,因为管理员必须能够在移动数据库时更改它,或者如果他想在dev / test / prod环境之间切换。

很久以来我发现了三种可能性:

  1. 通常通过使文件仅对运行应用程序的用户可读来回答第一个引用的问题。

    但在我的情况下这还不够(运行应用程序的用户是一个人。数据库用户/通行证是一般的,甚至不应该被人访问。)

  2. 第一个答案还建议在将连接数据写入文件之前加密连接数据

    使用这种方法,管理员不再能够配置连接字符串,因为他无法手动加密。

  3. 第二个引用的问题为这种情况提供了一种方法,但它似乎非常复杂。

我向你提问:

  1. 这是一个非常普遍的问题,所以没有任何一般的“怎么做”的方式,不知何故是一种“设计模式”?

  2. .NET的配置基础架构是否有一些支持?

  3. (可选,可能超出范围)我可以轻松地将其与NHibernate配置机制相结合吗?

更新:

回答第一个答案:有几个原因我想直接连接到数据库而不是使用Web服务

  • (N)Hibernate只能用于数据库,而不能用于web服务(对吗?)
  • 我们计划提供离线function,即如果数据库或网络应该关闭,用户可以继续他的工作。 为了解决这个问题,我正在考虑拥有一个本地的进程内数据库,例如SQL Server Compact,并使用MS Sync框架在它再次启动时立即与服务器数据库同步。

您是否有任何进一步的想法考虑到这一点?

实际上,WebService方法(在其他答案中提到)意味着您将NHibernate及其逻辑移动到Web服务。 然后,WebService使用WebService的方法公开应用程序可用的数据库function。

数据库实际上只有一个用户,WebService使用的用户,如果希望应用程序用户具有不同的数据库权限,则从WebService层抽象它

最后,WinForms应用程序只知道WebService通过WebService方法请求数据的位置,您可以在这两个端点之间应用任何所需的安全措施。

对于离线function而言,这一切都归结为以一种安全的方式将数据保存到本地存储并通过WebService提供同步方法

我实际上是使用与数据库通信的Web服务和只与Web服务通信的WinForm应用程序(.NET Compact Framework)完成此操作,如果没有蜂窝网络覆盖,它会将更改序列化到存储卡(数据是不重要,所以我的案件模糊/淫秽的安全措施,如果没有采取)

根据请求更新一个小例子(虽然要问一个例子,我觉得很奇怪)

您已经在ASP.NET WebService应用程序类型的项目中设置了域类和nhibernate配置以及(例如)您的存储库内容。 为了简单起见,我将只有一个Web服务类Foo (在Foo.asmx.cs中)以及单个Bar域类

所以你得到这个(实际实现各不相同):

 namespace FWS { [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.ComponentModel.ToolboxItem(false)] // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. // [System.Web.Script.Services.ScriptService] public class FooService : WebService { private readonly ILog errorLogger = LogManager.GetLogger("ErrorRollingLogFileAppender"); private readonly IDaoFactory daoFactory = new DaoFactory(); private readonly ISession nhSession = HibernateSessionManager.Instance.GetSession(); } [WebMethod] public Bar[] GetFavoriteBars(string someParam, int? onceMore){ return daoFactory.GetBarDao().GetFavoriteBars(someParam, onceMore); //returns a Bar[] } } 

我们抽象daobehaviour,或直接使用nhsession,暴露为webmethod。

现在,从WinForm应用程序,您需要做的就是Add a WebReference ,它对配置进行所有必要的更改,但也生成所有必需的类(在此示例中,它将创建一个Bar类,因为Web服务公开它)。

 namespace WinFormK { public class KForm(): System.Windows.Forms.Form { public void Do() { var service = new FWS.FooService(); string filePath = "C:\\temp\FooData.xml"; Bar[] fetched = service.GetFavoriteBars("yes!", null); //lets write this to local storage var frosties = new XmlSerializer(typeof(Bar)); TextReader reader = new StreamReader(filePath); try { var persisted = (T)frosties.Deserialize(reader); } catch(InvalidOperationException) { //spock, do something } finally { reader.Close(); reader.Dispose(); } } } } 

有些事情你必须注意:

  • 你基本上失去了懒惰的东西,或者至少你在winform应用程序中失去了它。 XML序列化程序无法序列化代理,因此您要么对这些集合/属性进行延迟提取,要么使用[XmlIgnore]属性,而后者依次执行序列化所暗示的内容。
  • 您无法返回WebMethod签名上的接口。 他们必须是具体的课程。 因此,返回IList必须转换为List或类似的东西
  • Web服务由IIS执行,可从Web浏览器中看到。 默认情况下,只会提供本地浏览器请求(但可以更改),因此您可以单独测试数据访问层与winform的function。
  • 接收端(winform app)不知道NHibernate。
  • 在上面的例子中,我为web方法的dao方法保留了相同的名称; 只要你没有在你的dao中保留nhibernate特定的方法(比如NHibernate.Criterions.Order参数),你可能会发现没有问题。 事实上,您可以根据需要在Web服务中拥有尽可能多的.asmx类,甚至可以将它们“映射”到相应的dao(如public class FooService : WebServicepublic class BarService : WebServicepublic class CheService : WebService ,其中每个对应于一个DAO)。
  • 您可能必须在端点之间编写某种轮询方法,以保持您呈现的数据新鲜。
  • WebService数据冗长; 非常如此。 建议在通过电线发送它们之前将它们拉出来(也可以加密它们)
  • win应用程序只知道配置条目: http://server/FWS/FooService.asmx
  • Webservices默认禁用会话。 记住在开始使用会话之前的用户数据。
  • 您可能必须为Web服务编写某种身份validation
  • 在上面的例子中,我返回一个Bar[]其中Bar与nhibernate映射。 通常情况可能并非如此,您可能需要编写一个辅助类WSBar ,它将原始Bar类调整为webservice和winform应用程序可以使用的类。 这个类实际上只是一个数据载体。 同样,这取决于您的域类和nhibernate存在多少集成以及如何使您的类复杂化:默认情况下,某些数据结构无法序列化。

  • 此模型可能不适合您已对应用程序执行的操作

首先,让不受信任的用户连接到数据库通常不是一个好主意。 很多事情都可能出错。 在中间放置一个Web服务。

如果你绝对必须这样做,那么即使他们获得用户名和密码也无所谓。 限制它们在数据库中的权限,以便它们只能执行一些具有内置安全检查的存储过程。

无论您做什么,都不能将特权用户的用户名/密码提供给不受信任的人。 这只是在寻找麻烦。 无论你试图在二进制文件中的加密字符串中隐藏凭证有多好,或者诸如此类,总有一种方法可以找到它们。 当然,是否有人真正做到这一点取决于你的数据有多有趣,但默默地希望那些带调试器的人只会让你一个人不是一个非常好的安全措施。

我认为这很难做到:就像你不希望stackoverflow的用户知道他的密码。 用户总是可以跟踪他的网络流量并查看用户/密码(您可以进行编码,但我认为它仍然不是100%确定)。

我认为您应该在用户和数据库之间添加一个webservice,每个用户都有一个唯一的id。

这就是数据库桌面应用程序糟糕的原因。 切片它没有好办法。 最好的办法是使用存储过程或Web服务。 基本上,另一个层可以锁定并控制对数据库的访问。