通过在Java中使用filtervalidation用户名和密码(与数据库联系)

以下是一段使用filter的Java代码,如果用户名和密码也是正确的,则每次都显示错误页面。 请帮助我,我对这个概念没有太多的认识。

String sql="select * from reg where username='"+user+"' and pass='"+pwd+"'"; rs=st.executeQuery(sql); if(rs.next()) { chain.doFilter(request,response); } else sc.getRequestDispatcher("/error.html").forward(request,response); 

String sql =“select * from reg where username ='”+ user +“'and pass ='”+ pwd +“'”;

这是一个非常糟糕的做法。 这种方法要求用户名和密码都通过简单的请求传递给普通用户。 而且,你有一个SQL注入攻击漏洞。

利用会话,在JSP / Servlet那里你有HttpSession 。 实际上也不需要使用Filter在每个请求上反复敲击数据库。 这是不必要的昂贵。 只需将User放在使用Servlet会话中,并使用Filter来检查每个请求的存在。

/login.jsp开始:

 <form action="login" method="post"> <input type="text" name="username"> <input type="password" name="password"> <input type="submit"> ${error} </form> 

然后,创build一个映射到/login url-patternLoginServlet ,并且执行doPost() ,如下所示:

 String username = request.getParameter("username"); String password = request.getParameter("password"); User user = userDAO.find(username, password); if (user != null) { request.getSession().setAttribute("user", user); // Put user in session. response.sendRedirect("/secured/home.jsp"); // Go to some start page. } else { request.setAttribute("error", "Unknown login, try again"); // Set error msg for ${error} request.getRequestDispatcher("/login.jsp").forward(request, response); // Go back to login page. } 

然后,创build一个映射到/secured/* url-patternLoginFilter (不过你可以select你自己的,例如/protected/*/restricted/*/users/*等等,但是这个必须至less包含所有的受保护的页面,您还需要将JSP放在WebContent中的相应文件夹中),并doFilter() ,如下所示:

 HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; HttpSession session = request.getSession(false); String loginURI = request.getContextPath() + "/login.jsp"; boolean loggedIn = session != null && session.getAttribute("user") != null; boolean loginRequest = request.getRequestURI().equals(loginURI); if (loggedIn || loginRequest) { chain.doFilter(request, response); // User is logged in, just continue request. } else { response.sendRedirect(loginURI); // Not logged in, show login page. } 

应该是这样的。 希望这可以帮助。

要了解UserDAO外观,您可能会发现这篇文章很有用。 它还介绍了如何使用PreparedStatement来保存您的Web应用程序免受SQL注入攻击。

也可以看看:

  • 如何在Java Web应用程序中Session过期时redirect到Login页面?
  • 身份validationfilter和servletlogin
  • 如何处理数据库中用户的authentication/授权?

使用准备好的语句,您的代码是SQL注入的公开邀请。

 Connection con = getMyConnection(); try { //no string concatenation, we use ? instead: PreparedStatement ps = con.prepareStatement("select * from reg where username=? and pass=?"); try { //actual value for parameters are set here: ps.setString(1, user); ps.setString(2, pwd); ResultSet rs = ps.executeQuery(); if(rs.next()) { chain.doFilter(request,response); } else { sc.getRequestDispatcher("/error.html").forward(request,response); } } finally { ps.close(); } } finally { con.close(); } 

现在为您的问题,请检查:

  • 表和列的名称是正确的(你没有“login”和“用户名”列?)
  • 这些值是真正正确的(例如在sqldevelopper中尝试查询)
  • 它使用ascii-7密码和用户名(这可能是一个编码问题)
  • 密码列包含真正的密码,而不是它的散列

这么多错误的东西…: – /

  1. 大的一个 – SQL注入 。 不要在代码中写入另一行SQL,直到你理解它。 这并不夸张, 不知道这个代码写的代码很可能会给攻击者任意访问你的数据库。
  2. 您不应该能够发出这样的查询,因为您不应该以明文存储密码。 相反,你应该计算和存储密码的某种(最好是盐)散列,然后散列提交的密码并进行比较。 例如,请参阅如何最好地存储用户login名和密码,以及如何在SO上提供密码 。 鉴于您的SQL注入漏洞,这是特别糟糕的。
  3. 因为你只是想知道一行是否存在,所以select * from reg是不必要的。 如果使用select 1 ,数据库将不必检查行的内容,并可以仅从索引提供查询结果。 如果你期望有很多的行, select 1 where exists ...会更快,因为这将允许数据库在查找至less一行后短路查询。
  4. 你不会在finally块中closures语句和结果集。 这意味着它们不能保证总是被抛弃(例如,如果SQLException )导致资源和连接泄漏。

首先,你真的应该使用参数化查询。 如果用户input'";DROP TABLE reg;作为用户名,您将遇到很大的麻烦。

另外,你确定用户名和密码是正确的吗? 大写怎么样?