今天做了一個小的登入程式,要求是使用者連續登入錯誤3次之後鎖定該使用者,過了一定的時間才能再次登入。于是乎在探讨的時候出現了以下的代碼:
private void UpdateErrortime()
{
SqlConnection conn = new SqlConnection(strcon);
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
conn.Open();
cmd.CommandText = "update T_User set [email protected] where [email protected]";
cmd.Parameters.AddWithValue("errortime",DateTime.Now);
cmd.Parameters.AddWithValue("@username",txtUserName.Text);
cmd.ExecuteNonQuery();
}
DateTime errortime = GetErrorTime();
//Subtract函數減去指定時間,傳回一個時間差,這個傳回值可以轉換成我們需要的形式,比如可以轉換層總共多少秒,或者總共是多少分。。。
TimeSpan span = DateTime.Now.Subtract(errortime);
double theseconds = span.TotalSeconds;
if (theseconds < 15)
{
MessageBox.Show("您已經連續3次輸入錯誤的密碼,已被系統鎖定,請15秒之後再次重試,或者到服務視窗解鎖");
//程式執行到此為止,後面代碼不再執行
return;
}
else
{
errorcount = 0;
UpdateError(errorcount);
}
這段代碼看似沒有問題,但實際應用中會發現隻需要修改本地的時間,就能繞過鎖定登入的限制,而用以下代碼則不會産生問題: int secondspan = GetErrorTime1();
//如果間隔時間小于解鎖時間則傳回程式
if (secondspan < 15)
{
MessageBox.Show("您已經連續3次輸入錯誤的密碼,已被系統鎖定,請15秒之後再次重試,或者到服務視窗解鎖");
//程式執行到此為止,後面代碼不再執行
return;
}
private int GetErrorTime1()
{
SqlConnection conn = new SqlConnection(strcon);
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
conn.Open();
cmd.CommandText = "select DATEDIFF([second],ErrorTime,getdate()) from T_User where [email protected]";
cmd.Parameters.AddWithValue("@username", txtUserName.Text);
//傳回一行一列
object obj = cmd.ExecuteScalar();
return Convert.ToInt32(obj);
}
BUG總結: 使用者鎖定的時間是通過用戶端時間驗證的而不是伺服器,通過完全調用伺服器的時間來做判斷,就能完美解決這一問題。