.Net连接池导致SQL Server密码更改后登录失败
配置文件中有不包含密码的连接字符串.Net连接池导致SQL Server密码更改后登录失败,.net,sql-server,login,connection,pool,.net,Sql Server,Login,Connection,Pool,配置文件中有不包含密码的连接字符串 Data Source=OurDataSource;Initial Catalog=OurCatalog;Integrated Security=False;UID=OurUser;Encrypt=True;TrustServerCertificate=False; 在我们的代码中,密码是从服务加载的,并附加如下: var connectionString = ConfigurationManager.ConnectionStrings["ourCS"].C
Data Source=OurDataSource;Initial Catalog=OurCatalog;Integrated Security=False;UID=OurUser;Encrypt=True;TrustServerCertificate=False;
在我们的代码中,密码是从服务加载的,并附加如下:
var connectionString = ConfigurationManager.ConnectionStrings["ourCS"].ConnectionString;
var builder = new SqlConnectionStringBuilder(connectionString);
var credential = GetPassword(builder.UserID);
builder.Password = credential.Password;
var connectionString = builder.ConnectionString;
using (var db = new SqlConnection(connectionString))
{
// Execute our query
}
密码服务每隔几个月更改一次密码,最近在更改密码后,我们开始收到下面的登录失败错误,并且帐户被锁定
Login failed for user 'OurUser'. Reason: Password did not match that for the login provided.
我的研究指出了连接池的问题,连接池仍然有打开的连接,这些连接试图对db进行身份验证并锁定它
我们所有的数据库通信都是使用上面的语句完成的,当调用dispose时,这些语句应该关闭连接。但是,在反编译System.Data.SqlClient.SqlConnection之后,dispose方法似乎没有关闭连接
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
// using CloseHandle and UnmapViewOfFile - no exposure
[ResourceExposure(ResourceScope.None)]
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
private void Dispose(bool disposing) {
if (disposing) {
// Nothing to do here
;
}
if (pMemMap != IntPtr.Zero) {
NativeMethods.UnmapViewOfFile(pMemMap);
pMemMap = IntPtr.Zero;
}
if (hMemMap != IntPtr.Zero) {
NativeMethods.CloseHandle(hMemMap);
hMemMap = IntPtr.Zero;
}
active = false;
}
~SqlDebugContext() {
Dispose(false);
}
有没有人遇到过这个问题并找到了解决方案?目前,它指出必须按如下方式调用ConnectionClose,因为它似乎并没有这样做
using (var db = new SqlConnection(connectionString))
{
// Execute our query
db.Close();
}
处理池连接只会将其返回到池。由于每个连接池都是一个不同的连接字符串,因此在使用新密码时,将在连接字符串时创建一个新池 我怀疑问题在于时间安排,在从服务检索新密码以构建新连接字符串之前,检索并重复使用原始密码以锁定帐户
如果密码更改是一个手动过程(例如“ALTER LOGIN”),然后服务配置了新密码,解决方案可能是使用静态方法更改服务代码中的密码。我认为只要该服务只有一个实例,问题就会得到缓解。您上面的代码应该处理SqlConnection,并在每次连接到数据库时创建一个新连接。用于第一个连接的连接字符串没有缓存在任何位置,正在使用传递给它的
connectionString
变量创建一个新的SqlConnection
根据您描述的症状,似乎GetPassword
方法没有始终返回正确的用户名密码组合
这可能是一个类似于@DanGuzman所描述的定时问题,
GetPassword
函数返回正确的密码,但是在创建SqlConnection之前密码会被更改。这将解释记录的间歇性登录成功和失败。我现在已经找到了答案。我有一个客户log4net appender,它从服务中获取连接字符串并添加密码
问题是我在自定义appender的构造函数中检索密码,而构造函数仅在app start:D时调用。因此,我必须在重写的append方法中移动对密码的检索
<log4net>
<root>
<level value="ALL" />
<appender-ref ref="RepositoryAppender" />
</root>
<appender name="RepositoryAppender" type="MyAppender, MyLibrary">
<threshold value="ALL" />
<bufferSize value="1" />
</appender>
</log4net>
我认为这可能是在计时,但这两天我们在sql日志中看到登录失败和登录成功的情况并非如此。很遗憾,我们自己没有更改密码的权限。@而且,更改密码不需要特殊权限。只需为ChangePassword方法指定一个包含旧密码和新密码的连接字符串。ChangePassword方法没有帮助,因为为了安全起见,我们存储没有密码的字符串。只有在填充了当前密码的情况下,它才起作用“连接字符串必须包含用户ID和当前密码”。在服务出于安全考虑返回密码之前,每个请求都不知道密码是什么。此外,更改密码需要特殊权限,因为它只是dbreader和writer帐户。此外,我们不想更改密码,因为这是由服务集中控制的。@AndyKing,我的意思是服务可以调用ChangePassword方法并将新密码返回到客户端应用程序。