我正在努力确保当用户输入用户名&密码,通过检查输入是否与用户表中的某些行匹配来完成验证。以下是目前的代码:单击登录按钮时,它不会响应。请建议我如何正确设置。谢谢
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());
}
}
答案 0 :(得分:1)
String CHECK_USER = "SELECT * FROM records WHERE username = '"+this.txtUser+"' AND password = '"+this.txtPass+"'";
您已通过用户名& sql查询中的密码,只有当用户名和密码匹配时才会进入阻止...
你应该让sql querylike这个 String CHECK_USER =“SELECT * FROM records”;
或者您可以像这样使用if块 如果(rs.next() { //登录成功代码 } 其他 { //登录失败 }
答案 1 :(得分:1)
您忘记在getText()
和txtUser
上致电txtPass
。
这是您修复查询的方法:
String CHECK_USER = "SELECT * FROM records WHERE username = '" + this.txtUser.getText() + "' AND password = '" + this.txtPass.getText() + "'";
您应该注意,将原始输入文本连接到查询会打开SQL注入漏洞。您应该使用PreparedStatement
代替,以便正确转义输入文本。
以下是正确实施此方法的方法,但缺少以下应该引起关注的事项:
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());
}
}
答案 2 :(得分:1)
基本上,逻辑是错误的。
你在做什么就是这个。
从用户处获取用户名和密码。
向数据库询问用户名与提供的用户名匹配的所有记录,密码与提供的密码相匹配。
对于每个这样的记录:
测试用户名是否匹配,如果不匹配则打开对话框。 那不会发生... ,因为您只选择了具有该用户名的记录。
测试密码是否匹配,如果不匹配则打开对话框。 那不会发生...... ,因为您只选择了使用该密码的记录。
你真正应该做的是:
从用户处获取用户名和密码。
选择与用户名和密码匹配的记录。
如果您匹配的记录的编号为零,则打印一条消息。
我还应该指出其他一些事情:
弹出一个对话框告诉用户他的用户名/密码是错误的。您真正需要做的是告诉您服务器中登录失败的其他内容。
当用户只获取用户名或密码不正确时,您不应该向他提供任何线索,其中一个是正确的。这样做可以让坏人更容易"找出正确的组合。
将密码以明文形式存储在数据库中是不良做法。最佳做法是存储密码的种子哈希值......并使用加密强哈希函数。
答案 3 :(得分: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+"'";
所以这里系统准备好了injection
所以好的方法就是这样,使用参数。
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");
}
答案 4 :(得分:-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");}