【问题标题】:How to configure database connection securely如何安全地配置数据库连接
【发布时间】:2011-02-27 08:29:39
【问题描述】:

相似但不一样:

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

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

或者我可以硬编码连接字符串,这很糟糕,因为如果数据库被移动或者如果他想在开发/测试/生产环境之间切换,管理员必须能够更改它。

这么久我发现了三种可能:

  1. 第一个参考问题的回答通常是使文件只对运行应用程序的用户可读

    但这对我来说还不够(运行应用程序的用户是一个人。数据库用户/密码是通用的,甚至不应该被这个人访问。)

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

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

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

我的问题:

  1. 这是一个非常普遍的问题,所以没有任何通用的“如何做”方式,某种“设计模式”吗?

  2. .NET 的配置基础设施有一些支持吗?

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

更新:

针对第一个答案:我想直接连接到数据库并且不使用网络服务有几个原因:

  • (N)Hibernate 只能用于数据库,不能用于 Web 服务(对吗?)
  • 我们计划提供离线功能,即如果数据库或网络出现故障,用户可以继续工作。为了管理这个,我正在考虑拥有一个本地的进程内数据库,例如SQL Server Compact,并在它再次启动时使用 MS Sync 框架将其与服务器数据库同步。

考虑到这一点,您有什么进一步的想法吗?

【问题讨论】:

  • 默默无闻的安全将被黑客入侵

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


【解决方案1】:

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

如果您绝对必须这样做,请确保即使他们获得用户名和密码也没关系。限制他们在数据库中的权限,以便他们只能执行少数具有内置安全检查的存储过程。

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

【讨论】:

  • 感谢您的回答。我想直接连接到数据库而不使用 Web 服务有几个原因,请参阅我的问题的更新。
  • @chiccodoro:在这种情况下,我猜你只能希望“同步框架”具有旨在处理此问题的内置安全性。我还没有真正使用它,所以我无法对此发表评论。
【解决方案2】:

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

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

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

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

我实际上是使用与 DB 通信的 web 服务和仅与 web 服务通信的 WinForm 应用程序 (.NET Compact Framework) 完成此操作的,在没有蜂窝网络覆盖的情况下,它会将更改序列化到存储卡 (数据并不重要,因此对于我的案例而言,未采取晦涩/淫秽的安全措施)

按要求更新一个小例子(尽管要求提供一个例子,但我确实觉得很奇怪)

您已经在 ASP.NET WebService Application 类型的项目中设置了域类和休眠配置以及(例如)您的存储库内容。为简单起见,我将只有一个 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[]
    }
}

我们将 dabehaviour 抽象化,或者直接使用 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<Bar> 必须转换为 List<Bar> 或类似的东西
  • Web 服务由 IIS 执行,可从 Web 浏览器中看到。默认情况下,只会提供本地浏览器请求(但可以更改),因此您可以将数据访问层与 winform 的功能分开测试。
  • 接收端(winform 应用程序)对 NHibernate 毫无了解。
  • 在上面的示例中,我为 web-methods 的 dao-methods 保留了相同的名称;只要您没有在您的 dao 中保留 nhibernate 特定的方法(可以说像 NHibernate.Criterions.Order 参数),您可能会发现没有问题。事实上,您可以在您的网络服务中拥有任意数量的 .asmx 类,甚至可能将它们“映射”到相应的 dao(如 public class FooService : WebServicepublic class BarService : WebServicepublic class CheService : WebService,其中每个都对应一个 DAO)。
  • 您可能必须在端点之间编写某种轮询方法以保持呈现的数据最新。
  • WebService 数据冗长;非常如此。建议在通过网络发送它们之前压缩它们或其他东西(也可以加密它们)
  • win应用只知道一个配置入口:http://server/FWS/FooService.asmx
  • Web 服务默认禁用会话。在开始使用会话获取用户数据之前,请记住这一点。
  • 您可能必须为 Web 服务编写某种身份验证
  • 在上面的示例中,我返回了一个Bar[],其中Bar 使用nhibernate 进行映射。通常情况并非如此,您可能需要编写一个辅助类WSBar,它使原始Bar 类适应webservice 和winform 应用程序可以使用的内容。这个类实际上只是一个数据载体。同样,这取决于与您的域类和 nhibernate 的集成程度以及您的类的复杂程度:某些数据结构默认情况下无法序列化。

  • 此模型可能不适合您对应用程序所做的工作

【讨论】:

  • 嗨捷豹。您能否扩展您对如何访问本地持久数据的回答? - 嗯.. 我也可能在本地重用网络服务的 NHibernateDatabase DAO 层,仅用于访问本地数据。
  • 感谢您提供详细信息!在你的陈述中“(我确实觉得很奇怪,尽管要求一个例子)”:我实际上并没有这么详细或例子的意思,我的问题更多是关于:你用什么方法来“保存你的数据”到本地存储并提供同步方法”
【解决方案3】:

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

我认为你应该在你的用户和你的数据库之间添加一个 web 服务,并为每个用户提供一个唯一的 id。

【讨论】:

    【解决方案4】:

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

    【讨论】:

    • 嗨 dotjoe,谢谢您的回答。 Webservices 可能不适用于我(请参阅我的问题的更新)。您还能想到什么“可以锁定并控制对数据库的访问的层”?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-14
    • 2011-11-10
    • 1970-01-01
    • 2011-01-21
    • 2012-09-14
    • 1970-01-01
    • 2013-02-01
    相关资源
    最近更新 更多