0

我试图确保当用户输入用户名和密码时,通过检查输入是否与用户表中的某些行匹配来完成身份验证。这是到目前为止的代码:单击登录按钮时它没有响应。请建议我如何正确设置它。谢谢

 private void dbConnection()
{
   try
   {
       Class.forName("com.mysql.jdbc.Driver");
       Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/maths_tutor", "root", "jesus");
       Statement stmt = conn.createStatement();
       String CHECK_USER = "SELECT * FROM records WHERE username = '"+this.txtUser+"' AND password = '"+this.txtPass+"'";
       ResultSet rs = stmt.executeQuery(CHECK_USER);

        while(rs.next())
        {
            String user = txtUser.getText();
            String pass = txtPass.getText();

            if(user.equals(rs.getString("username")))
            {
                if(pass.equals(rs.getString("password")))
                {
                    this.dispose();
                    new AboutTo().setVisible(true);
                }
                else JOptionPane.showMessageDialog(null, "Invalid Password");
            }
            else JOptionPane.showMessageDialog(null, "Invalid Username or Password");
        }



       stmt.close();
       rs.close();
       conn.close();
   }


   catch(SQLException | ClassNotFoundException er)
   {
       JOptionPane.showMessageDialog(null, "Exception:\n" + er.toString());
   }

}
4

5 回答 5

1

You forgot to call getText() on txtUser and txtPass.

This is how you could fix your query:

String CHECK_USER = "SELECT * FROM records WHERE username = '" + this.txtUser.getText() + "' AND password = '" + this.txtPass.getText() + "'";

You should note that concatenation of raw input text to queries will open vulnerability to SQL injection. You should use PreparedStatement instead so that the input text is properly escaped.

The following is a way to implement this properly, however lacks the following things that should be of concern to you:

  • You are storing passwords in clear text. You should use a hashing function such as SHA-1.
  • Every authentication will result in a new connection to the database. You should probably use a proper connection pool.

.

private boolean authenticate() throws SQLException {
    String dbUrl = "jdbc:mysql://localhost:3306/maths_tutor";

    // This query will simply count the matching rows, instead of actually selecting
    // them. This will result in less bandwidth between your application and the server
    String query = "SELECT count(*) AS num_records FROM records WHERE username = ? AND password = ?";

    // Obtaining the username and password beforehand could perhaps make it more clear
    // and prevent errors instead of pulling the data every time you need it
    String username = txtUser.getText();
    String password = txtPass.getText();

    // The try-with-resources block will make sure the resources are closed once we are done with
    // them. More information available at
    // http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
    try (
        // Open database connection
        Connection conn = DriverManager.getConnection(dbUrl, "root", "jesus");

        // Prepare the statement
        PreparedStatement stmt = conn.prepareStatement(query)
    ) {
        // Set the username and password for the SQL statement
        stmt.setString(1, username);
        stmt.setString(2, password);

        // Execute the query in a try block, to ensure that the resources
        // will be released
        try (ResultSet rs = stmt.executeQuery()) {
            if (rs.next()) {
                // If we got 1 or more matches, this means we successfully
                // authenticated. Otherwise, we failed authentication.
                return rs.getInt("num_records") > 0;
            }
        }
    }

    // Failed authentication.
    return false;
}

// Rename this to something meaningful according to your application
private void doAuthentication() {
    try {
        if (authenticate()) {
            // Do successful authentication handling
            this.dispose();
            new AboutTo().setVisible(true);
        } else {
            // Do failed authentication handling
            JOptionPane.showMessageDialog(null, "Invalid Username or Password");
        }
    } catch(SQLException er) {
        // Do error handling
        JOptionPane.showMessageDialog(null, "Exception:\n" + er.toString());
    }
}
于 2013-10-28T07:32:27.587 回答
1
String CHECK_USER = "SELECT * FROM records WHERE username = '"+this.txtUser+"' AND    password = '"+this.txtPass+"'";

您已经在 sql 查询中传递了用户名和密码,因此只有在用户名和密码匹配时才会进入 while block ...

你应该像这样进行sql查询 String CHECK_USER = "SELECT * FROM records";

或者您可以像这样使用 if 块 if(rs.next() { //登录成功代码 } else { //登录失败 }

于 2013-10-28T07:29:43.417 回答
1

基本上,逻辑是错误的。

你正在做的大约是这个。

  1. 从用户那里获取用户名和密码。

  2. 向数据库询问用户名与提供的用户名匹配且密码与提供的密码匹配的所有记录。

  3. 对于每个这样的记录:

    1. 测试用户名是否匹配,如果不匹配则打开一个对话框。 这不会发生......因为您只选择了具有该用户名的记录。

    2. 测试密码是否匹配,如果不匹配则打开一个对话框。 这不会发生......因为您只选择了具有该密码的记录。


你真正应该做的是:

  1. 从用户那里获取用户名和密码。

  2. 选择与用户名和密码匹配的记录。

  3. 如果您匹配的记录数为零,则打印一条消息。


我还应该指出一些其他的事情:

  • 弹出一个对话框告诉用户他的用户名/密码错误是题外话。您真正需要做的是告诉服务器中的其他内容登录失败。

  • 当用户得到的只是用户名或密码不正确时,你不应该向他提供任何线索表明用户名是正确的。这样做可以让“坏人”更容易找到正确的组合。

  • 将密码明文存储在数据库中是不好的做法。最佳做法是存储密码的种子散列......并使用加密强的散列函数。

于 2013-10-28T07:50:43.150 回答
0

可能的错误将在这条线附近

Class.forName("com.mysql.jdbc.Driver");
       Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/maths_tutor", "root", "jesus");

首先确保您已设置类路径并将 mysql 驱动程序添加到项目中
其次我会以下而不是上面的,实际上你为什么要让事情变得如此复杂?!

java.sql.Driver _dr=new com.mysql.jdbc.Driver();
java.util.Properties _pr=new java.util.Properties();
_pr.setProperty("user","root");
_pr.setProperty("password","jesus");
Connection conn = _dr.connect("jdbc:mysql://localhost:3306/maths_tutor", _pr);

最后一件事是要小心使用这样的代码

String CHECK_USER = "SELECT * FROM records WHERE username = '"+this.txtUser+"' AND password = '"+this.txtPass+"'";

所以这里系统已准备好注入
所以好的方法就是这样,使用参数。

String CHECK_USER = "SELECT * FROM records WHERE username = ? AND password = ?";//this will avoid sql injection
java.sql.PreparedStatement _st=conn.prepareStatement(CHECK_USER);
_st.setString(1, this.txtUser);
_st.setString(1, this.txtPass);



编辑:
顺便说一句,没有必要遍历结果集!只要调用该next()方法,如果它返回true,则表示用户输入了正确的用户/密码,否则。

ResultSet rs = stmt.executeQuery(CHECK_USER);
if(rs.next()){/*user exist*/
this.dispose();
new AboutTo().setVisible(true); }
else{
JOptionPane.showMessageDialog(null, "Invalid Username or Password");
}
于 2013-10-28T08:06:47.490 回答
-1
string query = "SELECT count(*) FROM [dbo].[login1] WHERE username='" + username.Text + "' and password='" + password.Text + "'";

SqlDataAdapter sda = new SqlDataAdapter(query, con);
DataTable dt = new DataTable();
sda.Fill(dt);

if (dt.Rows[0][0].ToString() == "1")
    {MessageBox.Show("YEAH");}
于 2015-12-10T06:41:07.247 回答