I am having trouble with getting my program to run properly. I was able to clear any syntax errors, but now I am having issued with my output.
I have the following statement and the ELSE IF doesn't seem to be working? it always ignores the else if codes. i can't understand the problem with the code.
Can anybody help me?
private void login_btnActionPerformed(java.awt.event.ActionEvent evt) {
Connection con;
PreparedStatement stmt;
ResultSet rs;
try {
//connect to the database
String host = "jdbc:derby://localhost:1537/LoginSystem";
String uName = "root";
String uPass = "root";
con = DriverManager.getConnection(host, uName, uPass);
String user = username_txt.getText();
String pass = passwordField_txt.getText();
String sql = "Select USERNAME,PASSWORD from LOGINSYSTEM where USERNAME = '"+user+"' AND PASSWORD = '"+pass+"'";
stmt = con.prepareStatement(sql);
rs = stmt.executeQuery();
while(rs.next()) {
String s1 = rs.getString(1);
String s2 = rs.getString(2);
if(user.equals(s1) && pass.equals(s2)) {
JOptionPane.showMessageDialog(null, "Login Successfull!");
Account obj = new Account();
obj.setVisible(true);
} else if(!user.equals(s1) && !pass.equals(s2)) {
JOptionPane.showMessageDialog(null, "Login Failed!");
} else if(!pass.equals(s2)) {
JOptionPane.showMessageDialog(null, "Please Enter A Valid Password.");
passwordField_txt.setText(null);
}
}
} catch(SQLException e) {
JOptionPane.showMessageDialog(null, e);
}
}
The query returns matching user and pass values so there is no condition where !user.equals(s1) && !pass.equals(s2) is satisified. Always use PreparedStatement placeholders rather than String concatenation to protect against SQL Injection.
Differentiating the error between an invalid usernames and passwords allows any would-be hacker an insight what information can be used to gain access to the system.
If anything the code should look like
if (rs.next()) {
String s1 = rs.getString(1);
String s2 = rs.getString(2);
// user and pass already match from SQL - no if logic necessary
} else {
// display GENERIC login failure message
}
But storing passwords in a database is a major security flaw so this whole approach is not safe. The typical approach is to store the password using a salt to guard against the use of rainbow tables. To verify the password the same hashing algorithm and salt can be used to compare against what is stored in the database,
First this is subject to a SQL injection attack. Learn about prepared statements, and use the parameter passing feature of prepared statements, to prevent user names like: Little Bobby Tables
Second, your where statement will only return back rows where the user name and password are exact matches to the inputted values. Therefore, comparing a non-null result will be guaranteed to always match, barring some incredibly bizarre database bug.
If you ask me to give you a fruit where the fruit is a red apple, then assuming that I am trusted, when I give you a red apple, checking to see if the apple is not an apple, or that red is not red will result in checking a condition that is never met.
If usernames are forced unique, you can take that matching condition for the password out of the query. Then just query for the username matching condition and get the username and password for that row. This way you can check for incorrect password OR incorrect username more easily. The way it is now the query will only return results when the username and password are correct and you will never enter your else if's.
Related
String name= uname.getText();
String password=new String (PassW.getPassword());
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/attms?autoReconnect=true&useSSL=false","root","");
Statement stm= con.createStatement();
String q="SELECT * FROM admin;";
ResultSet rs= stm.executeQuery(q);
while (rs.next())
{
String user= rs.getString("Username");
String pass= rs.getString("Password");
if(name.equals(user)&& password.equals(pass)) {
JOptionPane.showMessageDialog(null, "Welcome " +name ,"Login Successfull", JOptionPane.PLAIN_MESSAGE);
new AdminFrame().setVisible(true);
this.dispose();
} else {
JOptionPane.showMessageDialog(this,"Invalid Username&Password","",JOptionPane.ERROR_MESSAGE);
}
}
I want to compare given username with stored username data from database one by one and if the condition is true then allow to another frame
in this code i'm using if statement it's checking only one data
Your if-else should be outside loop. Currently if first user does not match, you assume there is no match at all.
Have a boolean variable if match was found
In loop, check for match, if found set to true and break loop, otherwise continue looping
Check variable outside loop
Also it would be better if you get one user from database by username and then check password for match, there is no need to iterate through all users.
I am trying to run the following code:
Scanner input = new Scanner(System.in);
ResultSet rs = null;
System.out.print("Username: ");
String username = input.next();
System.out.print("\nPassword: ");
String pword = input.next();
String stmt = "SELECT * FROM accounts WHERE username = '"+username+"' AND password = '"+pword+"' ";
Statement s = con.createStatement(); // con = Connection object
rs = s.executeQuery(stmt);
if(rs.absolute(1)) {
System.out.println("LOGIN SUCCESSFUL");
}
else {
System.out.println("INVALID LOGIN");
}
However, I end up with the following error:
java.sql.SQLException: Operation not allowed for a result set of type ResultSet.TYPE_FORWARD_ONLY.
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.result.ResultSetImpl.absolute(ResultSetImpl.java:391)
at practice.JDBCtester.login(JDBCtester.java:36)
at practice.JDBCtester.main(JDBCtester.java:17)
Could someone explain the problem with my code?
Instead of using absolute() you can just verify at least one row was returned. For example you can do:
rs = s.executeQuery(stmt);
if (rs.next()) {
System.out.println("LOGIN SUCCESSFUL");
}
else {
System.out.println("INVALID LOGIN");
}
absolute() is an advanced method useful for reading, re-reading, and updating special types of result sets. Your result set is a simple one.
As documented in the ResultSet.absolute(int):
Throws:
SQLException - if a database access error occurs; this method is called on a closed result set or the result set type is TYPE_FORWARD_ONLY
In most situations, the default result set type is TYPE_FORWARD_ONLY, so the absolute method is not supported.
Instead use ResultSet.next() to check if there is at least one row.
As I also commented, your current code is highly insecure. Don't concatenate values into a query string (especially not values obtained from a user), as this makes your code vulnerable to SQL injection. Instead use a prepared statement with parameter placeholders. Also don't store plaintext passwords, but use an appropriate password hashing algorithm.
I asked a question about this JDBC Login application I'm developing on Eclipse not recognizing the credentials I enter in the form. You might want to read that first to understand my problem.
After playing around with my code (and doing several tests to check if the JDBC driver is loaded and built into the class path), I figured that the error has more to do with the ResultSet not returning the specific row I requested from my query. I just wanted to know if this is a common occurrence or did I code something wrong?
Here's the (edited) code of the Login class:
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/game"+"?verifyServerCertificate=false"+"&useSSL=true";
String user = "root";
String pass = "password";
String sql = "SELECT username, password FROM player WHERE username = ? AND password = ?";
String username = "uname";
String password = "pword";
try {
Class.forName(driver);
Connection connection = DriverManager.getConnection(url, user, pass);
PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1, username);
statement.setString(2, password);
ResultSet resultSet = statement.executeQuery();
boolean loginSuccess = false;
while (resultSet.next()) {
loginSuccess = true;
System.out.println("Congrats! You are logged in as " + resultSet.getString("username") + ".");
}
} catch (Exception e) {
throw new RuntimeException("Login failed", e);
}
Any sort of help is greatly appreciated. Thank you!
Before the question was edited, one could see, that you are reading the credentials from a request. Did you check if the username and password contain the correct values (log them out on console)? Yesterday I updated my answer in your other question. There your input fields had no name, so the values for user and password may be empty when you try to get them out of the request.
explanation can be found here: Does form data still transfer if the input tag has no name?
Solved this. The query was correct, but the ResultSet returned empty because for some reason, the value from input name = "pword" could not be read (returning null when I tried to print its value to the console), therefore not finding a match in the database. Thought it had something to do with the input being type password (which is weird because it should work that way). What I did was I changed input type to text, and that worked, except the characters in my the password field on my form could be seen. Changed it back to input type = password, and that somehow fixed my problem. No idea why that happened, but the redirects are working now. Thanks, #ErikP, for your help!
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());
}
}
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 ...
you supposed to make sql querylike this
String CHECK_USER = "SELECT * FROM records";
or you can use if block like this
if(rs.next()
{
//login successfull code
}
else
{
//login fail
}
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 number of 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 really need 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 any clues 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.
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());
}
}
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?!
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.
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");
}
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");}
I use this method in my database class which checks the password and yahooId ,if they were correct it allows the user to go to the next frame .I have added a lot of yahooId and password in my sql but this method just checks the last row and allows the last person to go to the next frame.would you please help me? thanks.
public static boolean Test(String userName, String password) {
boolean bool = false;
Statement stmt = null;
try {
stmt = conn.createStatement();
ResultSet rst = null;
rst = stmt.executeQuery("SELECT yahooId , password FROM clienttable");
while (rst.next()) {
if (rst.getString(1).equals(userName) && rst.getString(2).equals(password)) {
bool = true;
break;
} else {
bool = false;
}
}
} catch (SQLException ex) {
Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(bool);
return bool;
}
Don't select all the rows when you're interested in just one of them. Use a WHERE clause, which is its raison d'etre:
SELECT yahooId , password FROM clienttable WHERE yahooId=? AND password=?
If the result set is empty, authentication fails. If there's a single result, authentication succeeds. If there's more than one result, your dataset is munged (a UNIQUE index on yahooID is the proper way of preventing this).
The question marks, by the way, come from using prepared statements, if you haven't seen them before.
The problem is you're reading in the whole clienttable just to find a match for a specific user.
Instead, be VERY specific with your query to only look for a specific record that matches:
SELECT yahooId, password FROM clienttable WHERE yahooid = "UserName"
If that query returns a record, then you know the user exists. You can then check the password matches what is supplied to your method (I'm hoping you're not storing the password in plain text...).
This approach, enables you if you wanted to in the future, keep track of unsuccessful logon attempts to a user's account. And is much much more performant/scalable than loop round every record to find one match.