首页 > 解决方案 > 使用 JSP 和 Servlet 验证密码

问题描述

我有一个用户登录 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>

标签: javahtmljspservletsforms

解决方案


您的数据库preparedStatement 中有错误:

  stm.setString(4, email);

4应该在这里吗?setString 的第一个参数对应 '?' 在你准备好的声明中。

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

你只有 1 个问号,所以应该是:

   stm.setString(1, email);

我可以做些什么来改进我的代码

将数据库逻辑与您的 servlet 分开。使用MVC 模式,它会让你的生活更轻松。

我怎样才能产生一个错误

您可以在 JSP 中使用 JSTL/EL 轻松实现此目的。在您的 servlet 中设置一个属性并将其转发到 jsp 页面。JSTL 将检查属性是否存在并显示适当的消息。

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

更高级的方法是实现 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;  
}

如果您有任何问题或其他问题,请告诉我,很乐意提供帮助。


推荐阅读