相似但不一样:
大家好,我有一个连接数据库服务器的C#WinForms应用程序。数据库连接字符串(包括通用用户/传递)放在NHibernate配置文件中,该文件与exe文件位于同一目录中。
现在我遇到了这个问题:运行应用程序的用户不应该知道普通数据库用户的用户名/密码,因为我不希望他直接在数据库中翻找。
或者我可以对连接字符串进行硬编码,这很糟糕,因为如果移动数据库或者他想在dev / test / prod环境之间切换,管理员必须能够更改它。
很久以来我发现了三种可能性:
第一个引用的问题通常由使文件仅对运行应用程序的用户可读来回答。
但在我的情况下这还不够(运行应用程序的用户是一个人。数据库用户/通行证是一般的,甚至不应该被人访问。)
第一个答案还建议在将连接数据写入文件之前对其进行加密。
使用这种方法,管理员无法再配置连接字符串,因为他无法手动加密。
第二个引用的问题为这种情况提供了一种方法,但它似乎非常复杂。
我向您提问:
这是一个非常普遍的问题,所以不是有任何一般的“怎么做”的方式,不知怎的是“设计模式”?
.NET的配置基础架构是否有一些支持?
(可选,可能超出范围)我可以轻松地将其与NHibernate配置机制结合起来吗?
更新
回答第一个答案:我有几个理由想直接连接到数据库,不使用网络服务:
您是否有任何进一步的想法考虑到这一点?
答案 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();
}
}
}
}
您必须注意以下事项:
IList<Bar>
必须转换为List<Bar>
或类似的内容NHibernate.Criterions.Order
参数),你可能会发现没问题。实际上,您可以根据需要在Web服务中拥有尽可能多的.asmx
个类,甚至可以将它们“映射”到相应的dao(例如public class FooService : WebService
,public class BarService : WebService
,public class CheService : WebService
每个对应一个DAO)。http://server/FWS/FooService.asmx
在上面的示例中,我返回Bar[]
,Bar
与nhibernate映射。通常情况可能并非如此,您可能需要编写辅助类WSBar
,以便将原始Bar
类调整为web服务和winform应用程序可以使用的类。这个类实际上只是一个数据载体。同样,这取决于你的域类和nhibernate存在多少集成以及你的类如何复杂:某些数据结构默认不能序列化。
此模型可能不适合您已对应用程序执行的操作
答案 2 :(得分:1)
我认为很难做到:就像你不希望stackoverflow的用户知道他的密码。 用户总是可以跟踪他的网络流量并查看用户/密码(您可以使用编码,但我认为它仍然不是100%确定)。
我认为您应该在用户和数据库之间添加一个web服务,并为每个用户添加唯一ID。
答案 3 :(得分:1)
这就是数据库桌面应用程序糟糕的原因。切片它没有好办法。最好的办法是使用存储过程或Web服务。基本上,可以锁定另一个层并控制对数据库的访问。