C#多用户登录表单无法写入SQL Server数据库及验证异常排查
问题排查与解决方案
已确认的问题根因
- 用户类型选择空引用异常:
user_type.SelectedItem在用户未主动选择用户类型时为null,直接调用ToString()方法会直接触发异常,进入catch分支弹出通用错误提示。 - SQL查询逻辑漏洞+SQL注入风险:当前查询仅过滤用户名和密码,未将用户类型加入查询条件,若账号密码匹配但用户类型选择错误,程序无任何提示反馈,用户感知为登录无响应。同时字符串拼接SQL的写法存在严重SQL注入风险,攻击者可通过特殊输入绕过登录验证。
- 匹配成功后未中断逻辑:用户类型匹配完成跳转页面后,未添加
break或return终止循环,逻辑冗余。 - 数据写入缺失用户类型字段:多用户表单无法正常存库,是因为新增用户的INSERT语句未加入
usertype字段赋值,若该字段在数据库中设置为非空约束,写入操作会直接触发约束错误失败。
可行修复方案
1. 登录逻辑修复(替换原有代码即可)
private void button1_Click(object sender, EventArgs e) { // 先做前端校验,避免空值触发异常 if (string.IsNullOrWhiteSpace(username.Text) || string.IsNullOrWhiteSpace(password.Text) || user_type.SelectedItem == null) { MessageBox.Show("请填写完整的账号、密码并选择用户类型", "输入错误", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } try { // 使用参数化查询,避免SQL注入,同时直接加入用户类型过滤,无需后续循环判断 string query = "SELECT * FROM log_data WHERE username = @username AND password = @password AND usertype = @usertype"; using (SqlCommand cmd = new SqlCommand(query, sqlco)) { // 传入参数,自动处理特殊字符转义 cmd.Parameters.AddWithValue("@username", username.Text.Trim()); cmd.Parameters.AddWithValue("@password", password.Text.Trim()); cmd.Parameters.AddWithValue("@usertype", user_type.SelectedItem.ToString()); SqlDataAdapter sda = new SqlDataAdapter(cmd); DataTable dt = new DataTable(); sda.Fill(dt); if (dt.Rows.Count > 0) { string loginUserType = dt.Rows[0]["usertype"].ToString(); MessageBox.Show("You are logged in as " + loginUserType); // 根据用户类型跳转对应页面 switch (user_type.SelectedIndex) { case 0: new customer().Show(); break; case 1: new Staff().Show(); break; case 2: new Trainer().Show(); break; } this.Hide(); } else { MessageBox.Show("账号、密码或用户类型错误,请重新输入", "登录失败", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } catch (Exception ex) { // 调试阶段可输出ex.Message排查具体错误,生产环境可隐藏详细报错 MessageBox.Show("登录出错:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { sqlco.Close(); } }
2. 数据写入逻辑修复
新增用户时,INSERT语句必须加入usertype字段的参数赋值,示例写法:
string insertSql = "INSERT INTO log_data (username,password,usertype) VALUES (@username,@password,@usertype)"; // 按参数化查询的方式传入三个字段的值即可,确保usertype的值和数据库存储的格式完全一致
内容的提问来源于stack exchange,提问作者Judel Dobbs
相关产品推荐
相关产品推荐

