这几天做了一个登陆验证的案例,主要功能就是:用户输入密码进行登陆,如果输错密码三次则15分钟内不能登陆。
这个案例确实不复杂,但是其中的逻辑第一次理解确实很别扭。
从这个小案例中,我得到了几个启示,并打算以后写类似的程序都执行此标准
1.该项目中,和sql有关的操作统统放到SqlHelper中 ---所有相同的操作都应该单独定义成一个助手类。
2.该项目中,使用了参数化查询有效防止了sql注入漏洞 ---所有关于查询的并且值由用户输入的sql语句,一律不准用字符串拼接
3.该项目中,判断用户是否存在的办法是使用SqlDataReader读取数据,然后判断dr.HasRows ---
这样做简便了查询,而且将整行的值取出,其他数据可以被另外代码使用
从这个项目中,我学到了这几点新知识
1.比较数据库中存储的时间和当前的时间相差多少分钟、多少小时、多少天……都可以使用dateDiff函数。而不需要将它取出来用.NET的DateTime类来处理(利用TimeSpan=DateTime-DateTime)
2.用户密码输错三次15分钟后的业务逻辑
窗体文件:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data;
using System.Data.SqlClient;namespace 密码输错三次15分钟后重试
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}private void btnLogin_Click(object sender, EventArgs e)
{
if (String.IsNullOrWhiteSpace(txtUserName.Text)
|| String.IsNullOrWhiteSpace(txtPassWord.Text))
{
MessageBox.Show("输入有误!");
return;
}using (SqlConnection conn = new SqlConnection("server=.;database=WebSite;uid=sa;pwd=123456"))
{
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "select *,datediff(minute, uLastErrTime,getdate()) from UserInfo where [email protected]";
cmd.Parameters.Add(new SqlParameter("@name", txtUserName.Text.Trim()));conn.Open();
//使用using对SqlDataReader进行资源管理
using (SqlDataReader dr = cmd.ExecuteReader())
{if (dr.HasRows)
{
dr.Read();if (dr.GetInt32(5) > 15)
{
//重置uErrTimes
SqlHelper.ResetErrTimes(dr.GetInt32(0));
}//加上这句话,可以解决结果集不同步的情况
//判断次数只能在时间小于15分钟的情况下才能进行
if (dr.GetInt32(5) <= 15)
{
if (dr.GetInt32(3) >= 3)
{
MessageBox.Show("密码错误已三次,请在15分钟后登陆!");
return;
}
}if (String.Equals(dr.GetString(2), txtPassWord.Text.Trim()))
{
MessageBox.Show("登陆成功!");
}
else
{
MessageBox.Show("密码错误,登陆失败");
//更新错误次数
SqlHelper.UpdateErrTimes(dr.GetInt32(0));
//记录错误时间
SqlHelper.RecordErrTime(dr.GetInt32(0));
}}
else
{
MessageBox.Show("不存在此账户!");
return;
}
}}
}
}
}
}
SQlHelper.cs助手类
//文件:SqlHelper.cs
//作者:Me
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Windows.Forms;namespace 密码输错三次15分钟后重试
{
/// <summary>
/// 包含各种对数据库的操作
/// </summary>
class SqlHelper
{
/// <summary>
/// sql链接字符串
/// </summary>
private static string sqlStr = "server=.;database=WebSite;uid=sa;pwd=123456";/// <summary>
/// 更新错误次数
/// </summary>
/// <param name="id"></param>
public static void UpdateErrTimes(int id)
{
using (SqlConnection conn = new SqlConnection(sqlStr))
{
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "update UserInfo set uErrTimes=uErrTimes+1 where [email protected]";
cmd.Parameters.Add(new SqlParameter("@id", id));
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show("数据库失败!" + ex.Message);
}
}
}}
/// <summary>
/// 重置错误次数
/// </summary>
/// <param name="id"></param>
public static void ResetErrTimes(int id)
{
using (SqlConnection conn = new SqlConnection(sqlStr))
{
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "update UserInfo set uErrTimes=0 where u[email protected]";
cmd.Parameters.Add(new SqlParameter("@id", id));
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show("数据库失败!" + ex.Message);
}
}
}
}/// <summary>
/// 记录错误时间
/// </summary>
/// <param name="id"></param>
public static void RecordErrTime(int id)
{
using (SqlConnection conn = new SqlConnection(sqlStr))
{
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "update UserInfo set uLastErrTime=getdate() where [email protected]";
cmd.Parameters.Add(new SqlParameter("@id", id));try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show("数据库失败!" + ex.Message);
}
}
}
}}
}
数据库查询的一般写法:从登陆验证小案例中得到的一些启示和经验,布布扣,bubuko.com