如何从数据库同一行获取指定用户数据?修复登录验证查询漏洞
我希望从数据库的同一行获取两个值,但当前查询会读取表中所有匹配的密码,导致登录验证漏洞:输入用户名Max和密码5678(Alex的密码)可登录Max账号,输入Alex的用户名和1234(Max的密码)也可登录Alex账号。我知道当前查询存在问题,仅需读取指定用户对应的密码,请问该如何实现?当前使用的查询语句如下:
Query name = session.createQuery("SELECT username FROM Accounts WHERE NOT EXISTS ( SELECT username FROM Accounts WHERE username = '" + user[2] + "')"); Query pass = session.createQuery("SELECT password FROM Accounts WHERE password = '" + user[3] + "'"); Query mail = session.createQuery("SELECT email FROM Accounts WHERE NOT EXISTS ( SELECT email FROM Accounts WHERE email = '" + user[3] + "')");
问题分析与解决方法
核心问题
你当前的登录逻辑是分开校验“用户名是否存在”和“密码是否存在”,完全没关联两者所属的同一行数据,这才导致跨用户登录的漏洞。同时,直接用字符串拼接SQL语句还存在SQL注入风险,属于严重安全隐患。
正确实现方式
1. 单查询验证用户名与密码的对应关系
应该在一个查询中,根据输入的用户名精准查询其对应的密码,再在代码中对比输入密码是否匹配。示例代码:
// 使用参数化查询避免SQL注入 Query query = session.createQuery("SELECT password FROM Accounts WHERE username = :username"); query.setParameter("username", user[2]); // 绑定用户名参数 List<String> result = query.list(); if (!result.isEmpty()) { String storedPassword = result.get(0); // 注意:实际项目中禁止明文存储/对比密码,需用哈希算法(如BCrypt)处理 if (storedPassword.equals(user[3])) { // 登录成功逻辑 System.out.println("登录成功"); } else { // 密码错误 System.out.println("密码错误"); } } else { // 用户名不存在 System.out.println("用户名不存在"); }
2. 更优方案:查询完整用户对象
如果需要同时获取用户邮箱等其他信息,可直接查询整个Accounts对象,一次性拿到同一行的所有数据:
Query query = session.createQuery("FROM Accounts WHERE username = :username"); query.setParameter("username", user[2]); List<Accounts> users = query.list(); if (!users.isEmpty()) { Accounts targetUser = users.get(0); if (targetUser.getPassword().equals(user[3])) { // 登录成功,直接调用对象方法获取其他信息 System.out.println("登录成功,邮箱:" + targetUser.getEmail()); } else { System.out.println("密码错误"); } } else { System.out.println("用户名不存在"); }
3. 关键注意事项
- 绝对禁止字符串拼接SQL,必须使用参数化查询(
setParameter)防范SQL注入。 - 密码不能明文存储,用户注册时需用哈希算法(如BCrypt、Argon2)加密,验证时对输入密码做相同哈希后再对比。
内容的提问来源于stack exchange,提问作者Maksim1251
相关产品推荐
相关产品推荐

