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

时间:2010-06-03 14:29:00

标签: c# database nhibernate connection-string app-config

相似但不一样:

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

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

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

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

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

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

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

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

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

  4. 我向您提问:

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

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

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

    4. 更新

      回答第一个答案:我有几个理由想直接连接到数据库,不使用网络服务

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

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

4 个答案:

答案 0 :(得分:5)

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

如果您必须这样做,请将其设置为即使获得用户名和密码也无关紧要。限制他们在数据库中的权限,以便他们只能执行一些具有内置安全检查的存储过程。

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

答案 1 :(得分:3)

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

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

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

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

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

根据要求更新一个小例子(我觉得这很奇怪但要问一个例子)

您已经在ASP.NET WebService Application类型的项目中设置了域类和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,暴露为网络方法。

现在,从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<Bar>必须转换为List<Bar>或类似的内容
  • Web服务由IIS执行,可从Web浏览器中看到。默认情况下,只会提供本地浏览器请求(但可以更改),因此您可以分别测试数据访问层与winform的功能。
  • 接收端(winform app)不知道NHibernate。
  • 在上面的示例中,我为web方法的dao-methods保留了相同的名称;只要你没有在你的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
  • Web服务默认禁用会话。记住在开始使用会话之前的用户数据。
  • 您可能需要为webservice编写某种身份验证
  • 在上面的示例中,我返回Bar[]Bar与nhibernate映射。通常情况可能并非如此,您可能需要编写辅助类WSBar,以便将原始Bar类调整为web服务和winform应用程序可以使用的类。这个类实际上只是一个数据载体。同样,这取决于你的域类和nhibernate存在多少集成以及你的类如何复杂:某些数据结构默认不能序列化。

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

答案 2 :(得分:1)

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

我认为您应该在用户和数据库之间添加一个web服务,并为每个用户添加唯一ID。

答案 3 :(得分:1)

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