【问题标题】:ConnectionString loses password after connection.OpenConnectionString 连接后丢失密码。打开
【发布时间】:2012-09-17 21:27:00
【问题描述】:

我正在使用 ADO.NET 从服务器上的数据库中获取一些信息,
所以这就是我所做的:

string conStr = "Data Source=myServer\SQLEXPRESS;Initial Catalog=DBName;User ID=myUser;Password=myPassword";

SqlConnection conn = new SqlConnection(conStr);

conn.Open();
// do stuff
conn.Close();

但在调用 Open 方法后,我注意到 conn.ConnectionString 正在丢失密码,因此它变为:

"Data Source=myServer\SQLEXPRESS;Initial Catalog=DBName;User ID=myUser;"

这会导致任何 SqlCommand 后缀异常
如何解决这个问题?
注意:奇怪的是这并不总是发生
编辑:我认为它与它自己的命令没有任何关系,但无论如何

SqlCommand command = new SqlCommand("select GetDate()", conn);
SqlDataReader reader = command.ExecuteReader();

【问题讨论】:

  • 对于初学者来说,执行 conn.Open() 后您是否有实际代码,否则您将根据上面示例中的内容打开它然后关闭它..
  • conStr 不能在您发布的代码中被SqlConnection 修改。您是否正在尝试查看 conn.ConnectionString (或一些类似的属性?)。
  • @insta:这就是 OP 所说的:“我注意到 conn.ConnectionString 正在丢失密码”
  • SqlConnection出于安全考虑会去掉密码是不是不合理?
  • @Star:那么我必须同意 DJ_KRAZE 的观点,即这毫无意义。为什么要使用除了返回数据库中的当前时间之外什么都不做的查询? DateTime.Now 会更有效率。

标签: c# ado.net


【解决方案1】:

出于安全原因,这是设计使然。来自MSDN

ConnectionString 类似于 OLE DB 连接字符串,但不相同。与 OLE DB 或 ADO 不同,返回的连接字符串与用户设置的 ConnectionString 相同,如果 Persist Security Info 值设置为 false(默认值),则减去安全信息。 除非您将 Persist Security Info 设置为 true,否则用于 SQL Server 的 .NET Framework 数据提供程序不会保留或返回连接字符串中的密码。

【讨论】:

  • 太好了,我在某处读到过,但不知道如何使用它,你能告诉我如何使用它吗?因为我在任何地方都看不到 Persist Security Info,谢谢
  • @Star,我给你的链接中有一个例子。只需在连接字符串中包含“Persist Security Info=True”。但无论如何,你不应该这样做......如果你需要 ConnectionString 属性来保留密码,你可能没有正确使用它。
  • 我明白了,所以你知道我可能错过了什么吗?再次非常感谢你:)
  • @Star,我最好的猜测是您在关闭 SqlConnection 后重用它;你应该创建一个新的。在没有看到更多代码的情况下,这是我能做的最好的事情......
  • 静默删除部分连接字符串。默认情况下!并且只有在它第一次使用之后……这是确保开发人员浪费时间调试奇怪问题的好方法。就像代码任意抛出 SqlException: Login failed for user ... 一样,因为您在错误的时间检查了连接字符串。这是一种奇怪的安全方式。他们至少可以让它抛出异常而不是返回虚假数据!
【解决方案2】:

查看连接字符串,为了将密码保留在 ConnectionString 属性中您必须将"Persist Security Info=true;" 添加到连接字符串本身

以下示例将删除密码:

string conStr = "Data Source=localhost;Initial Catalog=MyDatabase;User Id=MyUser;Password=MyPassword";
SqlConnection conn = new SqlConnection(conStr);
conn.Open();
conn.Close();
Console.WriteLine(conn.ConnectionString);

以下示例将密码保存在conn.ConnectionString

string conStr = "Persist Security Info=True;Data Source=localhost;Initial Catalog=MyDatabase;User Id=MyUser;Password=MyPassword";
SqlConnection conn = new SqlConnection(conStr);
conn.Open();
conn.Close();
Console.WriteLine(conn.ConnectionString);

它是在连接字符串本身而不是SqlConnection对象中设置的属性,我将它放在连接字符串的开头只是为了您不必滚动查看它,它可以在连接中的任何位置字符串,我通常在最后看到它。

正如其他人所说,如果您需要这样做,您很可能没有完全按照预期使用 SqlConnection 对象。

【讨论】:

    【解决方案3】:

    您可能希望添加自己的验证,但这将采用标准 SqlConnection(没有持久安全性)并访问私有 ConnectionOptions 属性以检索连接字符串。

    public static string SqlConnectionToConnectionString(SqlConnection conn)
    {
        System.Reflection.PropertyInfo property = conn.GetType().GetProperty("ConnectionOptions", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        object optionsObject = property.GetValue(conn, null);
        System.Reflection.MethodInfo method = optionsObject.GetType().GetMethod("UsersConnectionString");
        string connStr = method.Invoke(optionsObject, new object[] { false }) as string; // argument is "hidePassword" so we set it to false
        return connStr;
    }
    

    请注意,如果 MS 更改底层实现,这可能会中断,因为我们正在使用反射。我不建议这是最好的方法,但这是一种方法。

    【讨论】:

      猜你喜欢
      • 2012-06-05
      • 2016-09-29
      • 2018-03-14
      • 1970-01-01
      • 2019-01-25
      • 2013-02-06
      • 2020-05-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多