Java Servlet登录页面无需正确凭据即可登录问题求助
登录验证失效问题排查与修复
我是StackOverflow新手,近期用Java Servlet和数据库开发了带登录、注册功能的项目。昨天代码运行正常:输入错误凭据时,会提示“未找到数据,请点击注册”;但今天跑相同代码,输错凭据居然直接跳过验证登录了,求帮忙解决。
MyShopDAOimpl代码
package login.sg.registration; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; public class ShopDAOimpl implements ShopDAO { static Connection con; static PreparedStatement ps; @Override public int insertShopName(Shop s) { int status=0; try { con=MyConnectionProvider.getCon(); ps=con.prepareStatement("insert into shop123 (id,shopName,password,ownerName,address) values(?,?,?,?,?)"); ps.setString(1, s.getId()); ps.setString(2, s.getShopname()); ps.setString(3, s.getPassword()); ps.setString(4, s.getName()); ps.setString(5, s.getAddress()); //System.out.println("new comment" + s.getShopname()); status=ps.executeUpdate(); System.out.println("insert ps " + ps); con.close(); }catch(Exception e) { System.out.println(e); } return status; } @Override public Shop getShop(String Shopname, String pass) { Shop s= new Shop(); try { con=MyConnectionProvider.getCon(); //System.out.println("after connection"); ps=con.prepareStatement("select * from shop123 where shopname=? and password=?"); ps.setString(1, Shopname); ps.setString(2, pass); //System.out.println(ps); System.out.println(Shopname); ResultSet rs=ps.executeQuery(); while(rs.next()) { s.setShopname(rs.getString(1)); s.setPassword(rs.getString(2)); s.setName(rs.getString(3)); } }catch(Exception e) { System.out.println(e); } return s; } }
LoginRegister代码
package login.sg.registration; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/LoginRegister") public class LoginRegister extends HttpServlet { private static final long serialVersionUID = 1L; public LoginRegister() { super(); // TODO Auto-generated constructor stub } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ShopDAO S= new ShopDAOimpl(); String submitType=request.getParameter("submit"); if(submitType.equals("login")){ String shopName=request.getParameter("name"); // System.out.println(shopName); String password=request.getParameter("password1"); Shop s=S.getShop(shopName, password); System.out.println(s.getShopname()+s.getPassword()); request.setAttribute("message", s.getName()); request.getRequestDispatcher("Home.jsp").forward(request, response); }else if(submitType.equals("register")) { //System.out.println("register now function starts"); Shop s = new Shop(); s.setShopname(request.getParameter("shopname")); //System.out.println("test comment " +request.getParameter("shopname")); s.setPassword(request.getParameter("password1")); s.setName(request.getParameter("name")); s.setAddress(request.getParameter("address")); s.setId(request.getParameter("id")); request.getParameter ("password1"); S.insertShopName(s); request.setAttribute("successMessage","Registration Sucessfull!!!...login using your credentials"); request.getRequestDispatcher("login.jsp").forward(request, response); }else { request.setAttribute("message","Data Not Found,click on Register !!!"); request.getRequestDispatcher("login.jsp").forward(request, response); } } }
问题原因与修复方案
核心问题
- DAO层查询逻辑缺失判断:
getShop方法无论查询是否命中数据,都会返回一个新建的Shop对象。当输入错误凭据时,查询结果为空,但返回的对象属性都是默认值(比如空字符串),而非null。 - Servlet层未做有效性校验:登录分支里直接拿返回的
Shop对象跳转首页,完全没判断这个对象是否真的对应数据库里的有效用户。
修复步骤
1. 修改ShopDAOimpl的getShop方法
当查询结果为空时,返回null而非空对象:
@Override public Shop getShop(String Shopname, String pass) { Shop s = null; // 初始化为null try { con = MyConnectionProvider.getCon(); ps = con.prepareStatement("select * from shop123 where shopname=? and password=?"); ps.setString(1, Shopname); ps.setString(2, pass); ResultSet rs = ps.executeQuery(); if(rs.next()) { // 用if而非while,因为用户名密码唯一,只会有一条结果 s = new Shop(); // 仅当有数据时才创建对象 s.setShopname(rs.getString("shopName")); // 建议用列名而非索引,避免字段顺序变更出错 s.setPassword(rs.getString("password")); s.setName(rs.getString("ownerName")); } con.close(); // 确保连接关闭 } catch(Exception e) { e.printStackTrace(); // 打印完整栈轨迹,方便排查错误 } return s; }
2. 修改LoginRegister的doPost方法登录分支
增加用户有效性判断,无效则跳回登录页并提示错误:
if(submitType.equals("login")){ String shopName = request.getParameter("name"); String password = request.getParameter("password1"); Shop s = S.getShop(shopName, password); if(s != null) { // 仅当查询到有效用户时才跳转首页 request.setAttribute("message", s.getName()); request.getRequestDispatcher("Home.jsp").forward(request, response); } else { // 无匹配用户,返回登录页提示错误 request.setAttribute("message","Data Not Found,click on Register !!!"); request.getRequestDispatcher("login.jsp").forward(request, response); } }
额外优化建议
- 数据库连接管理:用
try-with-resources自动关闭Connection、PreparedStatement和ResultSet,避免资源泄漏:try (Connection con = MyConnectionProvider.getCon(); PreparedStatement ps = con.prepareStatement(sql)) { // 执行操作 } catch(Exception e) { e.printStackTrace(); } - 密码安全:不要明文存储密码,注册时对密码进行哈希(比如用BCrypt),登录时比对哈希值而非明文。
- 静态变量风险:DAO里的
con和ps是静态变量,多线程环境下会导致并发问题,改成方法内局部变量。
内容的提问来源于stack exchange,提问作者Gowtham Melur
相关产品推荐
相关产品推荐

