Java 我正在尝试验证用户名和密码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19628871/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
I'm trying to Validate username and password
提问by Vincent Uche
I am trying to ensure that when a user enters username & password, authentication is done by checking if input matches some row in the user table. Here is the code so far: It doesn't respond when the login button is click. Please suggest how I can set it right. Thanks
我试图确保当用户输入用户名和密码时,通过检查输入是否与用户表中的某行匹配来完成身份验证。这是到目前为止的代码:单击登录按钮时它没有响应。请建议我如何正确设置。谢谢
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());
}
}
回答by Kuldeep Choudhary
String CHECK_USER = "SELECT * FROM records WHERE username = '"+this.txtUser+"' AND password = '"+this.txtPass+"'";
you have passed username & password in sql query so it go in while block only if username And password will match ...
您已经在 sql 查询中传递了用户名和密码,因此只有当用户名和密码匹配时它才会进入 while 块...
you supposed to make sql querylike this String CHECK_USER = "SELECT * FROM records";
你应该像这样进行 sql 查询 String CHECK_USER = "SELECT * FROM records";
or you can use if block like this if(rs.next() { //login successfull code } else { //login fail }
或者你可以像这样使用 if 块 if(rs.next() { //登录成功代码 } else { //登录失败 }
回答by Ben Barkay
You forgot to call getText()
on txtUser
and txtPass
.
你忘了打电话getText()
的txtUser
和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.
您应该注意,将原始输入文本连接到查询会打开 SQL 注入漏洞。您应该PreparedStatement
改用,以便正确转义输入文本。
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.
- 您以明文形式存储密码。您应该使用散列函数,例如 SHA-1。
- 每次身份验证都会导致与数据库的新连接。您可能应该使用适当的连接池。
.
.
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());
}
}
回答by Stephen C
Basically, the logic is wrong.
基本上,逻辑是错误的。
What you are doing is approximately this.
你正在做的大约是这样。
Get a username and a password from the user.
Ask the database for all records for which the user name is matches the supplied username and the password matches the supplied password.
For each such record:
Test if the user name matches, and open a dialog if it doesn't match. That won't happen ...because you only selected records with that user name.
Test if the password matches, and open a dialog if it doesn't match. That won't happen ...because you only selected records with that password.
从用户那里获取用户名和密码。
向数据库询问用户名与提供的用户名匹配且密码与提供的密码匹配的所有记录。
对于每个这样的记录:
测试用户名是否匹配,如果不匹配则打开一个对话框。 这不会发生……因为您只选择了具有该用户名的记录。
测试密码是否匹配,如果不匹配则打开一个对话框。 这不会发生......因为您只选择了具有该密码的记录。
What you really ought to be doing is:
你真正应该做的是:
Get a username and a password from the user.
Select the records that match the user name and password.
Print a message if the numberof records that you matched is zero.
从用户那里获取用户名和密码。
选择与用户名和密码匹配的记录。
如果匹配的记录数为零,则打印一条消息。
I should also point out some other things:
我还应该指出一些其他的事情:
Popping up a dialog box to tell the user his user name / password are wrong is beside the point. What you reallyneed to do is tell something else in your server that the login failed.
When the user gets just the username or just the password incorrect, you should not offer him anyclues that one was correct. Doing that makes it easier for "the bad guy" to work out the correct combination.
Storing passwords in clear in a database is Bad Practice. Best practice is to store seeded hashes of the passwords ... and use a cryptographically strong hashing function.
弹出一个对话框告诉用户他的用户名/密码错误是无关紧要的。您真正需要做的是告诉服务器中的其他内容登录失败。
当用户得到的只是用户名或密码不正确时,您不应该向他提供任何正确的线索。这样做可以让“坏人”更容易找到正确的组合。
在数据库中以明文形式存储密码是不好的做法。最佳做法是存储密码的种子散列......并使用加密强散列函数。
回答by Stephen C
The possible error would be near this line
可能的错误将在这条线附近
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/maths_tutor", "root", "jesus");
first make sure you have set the classpath and added the mysql driver to the project
second I would the following instead of the above, in fact why do you make things to much complex?!
首先确保你已经设置了类路径并将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);
and the last thing is beware about using this like of code
最后一件事是小心使用这样的代码
String CHECK_USER = "SELECT * FROM records WHERE username = '"+this.txtUser+"' AND password = '"+this.txtPass+"'";
so here the system is ready for injection.
so the good way would be like this, using parameters.
所以这里系统已准备好进行注射。
所以最好的方法是使用参数。
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);
EDIT :
by the way, there is no need to iterate over result set! simple just call the next()
method, if it returns true, so it means user has entered correct user/pass, else otherwise.
编辑:
顺便说一下,没有必要迭代结果集!简单只是调用该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");
}
回答by Khairul Amir
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");}