使用JSP和Servlet进行密码验证

时间:2018-10-23 16:34:30

标签: java html jsp servlets html-form

我有一个用户登录Html表单,我在其中获取用户的电子邮件和密码,并对照数据库进行检查。到目前为止,我具有以下代码,但是当我提交表单时,它不会转到指定的JSP页面。我可以做些什么来改进我的代码,并且当用户按下“提交”但仍然停留在同一页面上时,如何生成错误消息?

谢谢。

// SERVLET doPost方法

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userinp = request.getParameter("userinp"); //hidden type in html sign up form
        HttpSession s = request.getSession();
        User u = new User();
        if(userinp.equals("signup")) {
            u.setName(request.getParameter("name"));
            u.setLname(request.getParameter("lname"));
            u.setEmail(request.getParameter("email"));
            u.setPassword(request.getParameter("password"));
            s.setAttribute("User", u);
            //Save to DB
            u = (User)s.getAttribute("User");
            s.invalidate();
            UserM ud = new UserM(); //class which contains CRUD methods
            ud.createTable();
            ud.insert(u);
            ServletContext ctx = request.getSession().getServletContext();
            forwardTo(ctx, request, response, "/Somepage.jsp");

        } else if(userinp.equals("login")) {
            String pass1 = request.getParameter("pass");
            String email = request.getParameter("useremail");
            Connection conn = null;
            PreparedStatement stm = null;
            try {
                conn = ConnectionConfiguration.getConnection();
                stm = conn.prepareStatement("SELECT password FROM users WHERE email = ?");
                stm.setString(4, email);
                ResultSet resultSet = stm.executeQuery();
                while(resultSet.next()) {
                    String pass2 = resultSet.getString("password");
                    if(pass1.equals(pass2)) {
                        ServletContext ctx = request.getSession().getServletContext();
                        forwardTo(ctx, request, response, "/Somepage.jsp");
                        } else {
                            //code to generate "Wrong Password" message
                        }
                    }
                } catch(Exception e) {
                    e.printStackTrace();
                } finally {
                    if(stm != null) {
                        try {
                            stm.close();
                        } catch (SQLException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                    if(conn != null) {
                        try {
                            conn.close();
                        } catch (SQLException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }

        }
    }

// ForwardTo方法

public static void forwardTo(ServletContext ctx, HttpServletRequest req, HttpServletResponse resp, String dest)  throws ServletException
{
    RequestDispatcher rd = ctx.getRequestDispatcher(dest);
    try
    {
        rd.forward(req, resp);
    }
    catch(Throwable t)
    {
        t.printStackTrace();
        throw new ServletException(t);
    }
}

// HTML表单

<html>
<head>
<meta charset="ISO-8859-1">
</head>
<body>
<form action = "UserServ" method="POST">
<h3>Enter the details below to Sign In</h3><br>
Email: <input type="text" name="useremail" required><br>
Password: <input type="password" name="pass" required><br>
<input type="submit" value="Sign In">
</form>
</body>
</html>

1 个答案:

答案 0 :(得分:1)

您的数据库prepareStatement中存在错误:

  stm.setString(4, email);

这里应该有4个? setString的第一个参数对应于“?”在您准备好的陈述中。

   stm = conn.prepareStatement("SELECT password FROM users WHERE email = ?");

您只有1个问号,因此应该是:

   stm.setString(1, email);
  

我该怎么做才能改善代码

从servlet中分离数据库逻辑。使用MVC pattern,它将使您的生活更轻松。

  

以及如何产生错误

您可以在JSP中使用JSTL / EL轻松实现这一目标。在您的servlet中设置一个属性,并将其转发到jsp页面。 JSTL will check(如果属性存在)并显示相应的消息。

如果详细信息有误,您也可以将用户转到特定页面,如下面的示例所示。

更高级的方法是访问implement AJAX,这基本上是使用javascript异步调用servlet,从而不必刷新页面。您可以使用它来检查详细信息是否正确。

  

用户按下“提交”但仍然停留在同一页面上时的消息?

您的意思是如果他们没有输入任何详细信息?您可以使用javascript / jquery来做到这一点。文本字段为空时,也许可以禁止提交btn / form提交。

下面是您的servlet代码,我浓缩了您的数据库逻辑。用这种方法更容易管理:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    String userinp = request.getParameter("userinp"); //hidden type in html sign up form
    HttpSession s = request.getSession();
    User u = new User();
    ServletContext ctx = s.getServletContext();
    //check for null first, because if userinp is empty, then you will get a NPE
    if(userinp != null && userinp.equals("signup")) {
        u.setName(request.getParameter("name"));
        u.setLname(request.getParameter("lname"));
        u.setEmail(request.getParameter("email"));
        u.setPassword(request.getParameter("password"));
        s.setAttribute("User", u);
        //Save to DB
        u = (User)s.getAttribute("User");
        s.invalidate();
        UserM ud = new UserM(); //class which contains CRUD methods
        ud.createTable(); //why are you creating a table for each user? (you need to create a table called 'users' and just insert the new user there.
        ud.insert(u);

        forwardTo(ctx, request, response, "/Somepage.jsp");

    } else if( userinp != null && userinp.equals("login")) { //you should separate the register and login logic (easier to maintain in two different servlets
        String pass1 = request.getParameter("pass");
        String email = request.getParameter("useremail");


        //so instead of getting the password from the database, you can check to see if the details exist instead and return a boolean. 
        if(validate(email,pass1)){

        forwardTo(ctx, request, response, "/Welcome.jsp"); //user is logged in

        }else{

        forwardTo(ctx, request, response, "/Error.jsp"); //user is not logged in, details do not match

        }

    }

}

验证方法:

//this should be in a different class. So it's easier to maintain and can be used elsewhere. It's bad practice to have database logic in your servlet. Because what if you want to use this in a different servlet or another part of your application? (you don't want to copy and pasta it everywhere do you?)

public static boolean validate(String email, String password){          
     boolean status = false;  
    PreparedStatement pst = null;  
    ResultSet rs = null;  
     //if you put your getConnection method as a try condition, it will automagically close the connection for you. 
    try(Connection conn= ConnectionConfiguration.getConnection()){

        pst = conn.prepareStatement("select * from users where email=? and password=?;");  
        pst.setString(1, email);   //1 here corresponds to the first '?' in preparedStatement
        pst.setString(2, password);  //2 corresponds to the second '?'
        rs = pst.executeQuery();  

        status = rs.next();  //if there are any results, then status is true. 
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return status;  
}

如果您在任何地方有问题或其他问题,请告诉我。