如何实现登录功能支持用户名或邮箱两种方式输入登录
问题分析与解决方案
1. 核心问题:SQL语句逻辑错误
你的SQL查询语句存在语法和逻辑错误,导致OR条件未按预期生效:
原语句:
SELECT * FROM loginTable WHERE email or username = '"+txt_user.Text+"' AND password = '"+txt_pass.Text+"'
由于SQL中AND的优先级高于OR,这条语句实际执行的逻辑是:(email字段非空/非0) OR (用户名匹配输入且密码匹配),完全偏离了“用户名或邮箱匹配,同时密码匹配”的需求,而且单独写email会被当作布尔值判断,逻辑完全错误。
正确的SQL逻辑应该将OR的两个条件用括号包裹,确保先判断“用户名或邮箱匹配”,再和密码条件做AND:
SELECT * FROM loginTable WHERE (email = @userInput OR username = @userInput) AND password = @password
2. 关键改进:用参数化查询避免SQL注入
你当前的代码直接拼接用户输入到SQL语句中,存在严重的SQL注入风险,攻击者可通过构造特殊输入篡改SQL逻辑、窃取或破坏数据库数据,必须改用参数化查询。
3. 修正后的完整代码
替换logUser_Click方法中的代码如下:
private void logUser_Click(object sender, EventArgs e) { string userInput = txt_user.Text; string passwordInput = txt_pass.Text; // 空值校验,避免无效查询 if (string.IsNullOrWhiteSpace(userInput) || string.IsNullOrWhiteSpace(passwordInput)) { MessageBox.Show("请输入用户名/邮箱和密码", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); txt_user.Focus(); return; } try { con.Open(); // 使用参数化查询 string query = "SELECT COUNT(*) FROM loginTable WHERE (email = @UserInput OR username = @UserInput) AND password = @Password"; SqlCommand cmd = new SqlCommand(query, con); // 添加参数 cmd.Parameters.AddWithValue("@UserInput", userInput); cmd.Parameters.AddWithValue("@Password", passwordInput); // 执行查询,获取匹配的行数 int matchCount = (int)cmd.ExecuteScalar(); if (matchCount > 0) { Form1 f1 = new Form1(); f1.Show(); this.Hide(); } else { MessageBox.Show("登录信息错误,请重试", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); txt_user.Clear(); txt_pass.Clear(); txt_user.Focus(); } } catch (Exception ex) { MessageBox.Show($"错误:{ex.Message}", "异常", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { if (con.State == ConnectionState.Open) con.Close(); } }
额外优化点
- 增加输入空值校验,避免无意义的数据库查询
- 使用
ExecuteScalar替代SqlDataAdapter和DataTable,仅查询匹配行数,性能更优 - 捕获具体异常并显示错误信息,便于调试
- 显式判断连接状态后再关闭,避免重复关闭的错误
内容的提问来源于stack exchange,提问作者Branson Street
相关产品推荐
相关产品推荐

