我有一个桌面 C# 应用程序,几个客户端连接到 SQL 服务器。每个用户都有一个 ID 和密码。我想要的是防止已经登录的用户从另一台计算机登录。
我通过在登录时更新数据库'UserLoggedIn'=true中的字段来实现它,当用户注销时,字段更新为False。但是这个解决方案并不是最优的,如果系统崩溃或计算机意外关闭,数据库中的值将保持'UserLoggedIn'=True,并且该用户将永远无法再次登录到系统。
什么是最佳解决方案,并防止已经登录的用户从另一台计算机登录?
我有一个桌面 C# 应用程序,几个客户端连接到 SQL 服务器。每个用户都有一个 ID 和密码。我想要的是防止已经登录的用户从另一台计算机登录。
我通过在登录时更新数据库'UserLoggedIn'=true中的字段来实现它,当用户注销时,字段更新为False。但是这个解决方案并不是最优的,如果系统崩溃或计算机意外关闭,数据库中的值将保持'UserLoggedIn'=True,并且该用户将永远无法再次登录到系统。
什么是最佳解决方案,并防止已经登录的用户从另一台计算机登录?
而不是true
,在数据库中存储一个时间戳。确保在用户登录时定期更新它。
当他们登录时,如果它不是太新,请允许他们。也就是说:如果您在最后(比如说)30 秒内从另一台 PC 上看到了它们,那么认为该会话仍然存在,并拒绝新的登录。
这样,如果他们的另一台 PC 崩溃,时间戳将不会更新,最终会过期。
更新频率应该是到期超时的两倍左右。例如,如果您想要 1 分钟的会话到期,您应该每 30 秒更新一次时间戳。
我建议您使用以下查询检查用户是否已建立与数据库的连接
SELECT loginame as LoginName,program_name
FROM sys.sysprocesses
WHERE db_name(dbid)='my_database' and loginame='test_user'
如果返回的记录数大于零,那么您可以假设用户已经从您的应用程序连接到数据库。
如果您查看 MSDN 中的连接字符串属性,您会发现以下感兴趣的属性。这 2 个属性可以添加到您现有的连接字符串中,以进一步改进可以在上面的查询中定义的过滤器
应用程序名称- 应用程序的名称,如果未提供应用程序名称,则为“.Net SqlClient 数据提供程序”。(=上表中的程序名称)
工作站 ID - 连接到 SQL Server 的工作站的名称。(=上表中的主机名)
我相信无论客户端发生崩溃,此解决方案都可以正常工作,并且不需要您将状态保存在任何表中。