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");}
Related
I am trying to create a Login and Register form using Java and SQL Workbench. The Register form works properly as the Username and Password are added to the SQL Database. As for the Login form, everything looks fine. But, when it is executed, it skips the If Statement and goes straight to the Else Statement. The Username and Password are correct as I checked the SQL Database table. The output is a SqlSyntaxErrorException. Therefore, I think my syntax is wrong. Any help would be highly appreciated!
This is the code below:
if (e.getSource() == LOG_IN_BUTTON)
{
String userName = USER_NAME_TEXTFIELD.getText();
String password = PASSWORD_TEXTFIELD.getText();
try {
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/airline_connect",
"root", "Yasser1595");
String sql = "Select user_name, password from account where user_name=? and password=?";
st = connection.prepareStatement(sql);
st.setString(1, userName);
st.setString(2, password);
ResultSet rs = st.executeQuery(sql);
if (rs.next()) {
frame.dispose();
new MainGame();
JOptionPane.showMessageDialog(LOG_IN_BUTTON, "You have successfully logged in");
} else {
JOptionPane.showMessageDialog(LOG_IN_BUTTON, "Wrong Username & Password");
}
} catch (Exception exc) {
exc.printStackTrace();
}
}
Try the following,
ResultSet rs = st.executeQuery();
Don't pass the sql string to executeQuery. When you pass the sql string to executeQuery it considers it as plain text instead of prepared statement
You did not use PreparedStatement.executeQuery() but the parent's Statement.executeQuery(sql) which is a known pitfall. Also it is worth using try-with-resources with local variables. Not closing things can cause resource leaks.
String sql = "select user_name, password from account where user_name=? and password=?";
try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/airline_connect",
"root", "Yasser1595");
PreparedStatement st = connection.prepareStatement(sql)) {
st.setString(1, userName);
st.setString(2, password);
try (ResultSet rs = st.executeQuery()) { // No sql parameter.
if (rs.next()) {
frame.dispose();
new MainGame();
JOptionPane.showMessageDialog(LOG_IN_BUTTON, "You have successfully logged in");
return;
}
JOptionPane.showMessageDialog(LOG_IN_BUTTON, "Wrong Username & Password");
}
} catch (SQLException exc) {
exc.printStackTrace();
}
It still did not work
PASSWORD also is a function, but as no syntax errors happend, that probably is no problem. You might try "password" (= column name).
The column might store not the password - which is a security risk, should
the database be stolen in the future. It might store some hash of the password.
So:
String sql = "SELECT user_name, \"password\" "
+ "FROM account "
+ "WHERE user_name=? AND \"password\"=PASSWORD(?)";
First check how passwords (or their hashes) are stored.
It might also be the case that the password handling is done at the java side, for instance by taking the MD5 of the password and storing that.
Should all work, consider an other securite measure: if the password field is a JPasswordField one should ideally not work with a String, but a char[] that can be wiped out after usage (Arrays.setAll(pwdArray, ' ');). A String could reside long in memory, which might be a security risk.
I working on a log in system in Java and I am using PostgreSQL. I have a registration form that saves the user information to the database. It also hashes the password before storing. I am now trying to verify the password that the user enters against the hashed password in the database.
try {
//connects to the database
Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/cc", "pi", "server");
//prepares SELECT statement
PreparedStatement statement = conn.prepareStatement("SELECT username, user_pass FROM users WHERE username = '" + username +"';");
ResultSet result = statement.executeQuery();
String upass = new String(password.getPassword());
String user = "";
String pass = "";
while(result.next()){
user = result.getString("username");
pass = result.getString("user_pass");
}
if(username.equals(user) && BCrypt.checkpw(upass, pass)){
frame.dispose();
new CommunityCooks();
}
else{
JOptionPane.showMessageDialog(null, "incorrect credentials");
}
}
catch(SQLException f){
f.printStackTrace();
}
This is the section that I am trying to verify the password matches. The "password" variable is a JPasswordField and the "username" variable is a JTextField. The stored credentials are 'tester' for the username and password and I am able to verify them as local variables and fields. I think the issue I am having is with the translation of the JTextField and the JPasswordField. What I am looking for help on is getting the username and password that the user enters to verify against the stored credentials after the password is hashed from the registration form. The issue I am having is that I can run the application and the login frame opens. I enter the test credentials and it is not matching. I’m getting my incorrect credentials message. I am unclear about the syntax for comparing the stored username (not hashed) and the stored password (hashed) against the user input credentials in the JTextField and the JPasswordField. I thought what I had was correct but it appears to not be right. The testing I have done for it works to read the database and verify but it is not working when I implement it in my program. The only difference in the two is the use of the fields where the test did not use them. My test is below:
public class Main {
public static void main(String[] args) {
String firstName = "tester";
String lastName = "tester";
String email = "tester";
String username = "tester";
String password = "tester";
try {
//connects to the database
Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/cc", "pi", "server");
//inserts values into table
PreparedStatement statement = conn.prepareStatement("insert into users values(?,?,?,?,?)");
statement.setString(1, firstName);
statement.setString(2, lastName);
statement.setString(3, email);
statement.setString(4, username);
statement.setString(5, BCrypt.hashpw(password, BCrypt.gensalt()));
PreparedStatement st = conn.prepareStatement("SELECT username, user_pass FROM users WHERE username = '" + username + "';");
ResultSet result = st.executeQuery();
String u = null;
String p = null;
while (result.next()) {
u = result.getString("username");
p = result.getString("user_pass");
}
System.out.println(u);
System.out.println(p);
System.out.println(BCrypt.checkpw(password, p));
} catch(SQLException f){
f.printStackTrace();
}
}
}
The test output works and shows the username and the hashed password and stating that it is "true" to being verified.
Any guidance will be greatly appreciated. This is my first time using a hash system.
This query is not executed and the code going to catch block.
ISSUE in Query
May be in whileloop....
try {
getConnection();
String user = text.getText().trim();
String pass = password.getText().trim();
String query = "Select name,password from pharmacy.login where name = '" + user + "' and password = '" + pass + "'";
result = statement.executeQuery(query);
System.out.println("hii");
int count = 0;
while (result.next()) {
count++;
}
}
Your code is prone to SQL-injection, but given the situation please read-on.
In order to find the reason that the query is not executed, you should catch the exception and log it. It may provide useful information on how to solve your issue.
But if your target is just to count the records found, then you should change the query to:
select count(*) from pharmacy.login where name='...' and password='...'
However, your code is prone to SQL-injection.
Normally, you should use PreparedStatement with ? or an ORM framework to retrieve your user object, and the search criteria should be the username only.
select username, password from pharmacy.login where name = ?
The database contents in the Password field should be encrypted, and the input value of the password from the user should be encrypted also.
After retrieving the user object, you should compare the encrypted password field and the encrypted input password value.
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.
How could I check if the username and password (taken as input in a login page) match? All of the information is stored in a Derby DB. I just need to know if the correct password is entered for a username that is given.
Here is my code:
public void checkIdPw(String userName, String passWord) {
try {
stmt = conn.createStatement();
String checkPwforIdSQL = "SELECT PASSWORD FROM " + studentsTable + " WHERE USERNAME = '" + userName + "'";
stmt.executeQuery(checkPwforIdSQL);
stmt.close();
} catch(SQLException sqlExcept) {
sqlExcept.printStackTrace();
}
}
It is poor security to store passwords unencrypted and encrypting them with something like Bcrypt would be much better.
Something like the following should work for what you need. Using a PreparedStatement is crucial and simple string concatenation should never be done as it allows for SQL injection attacks.
PreparedStatement stmt = conn.prepareStatement(
"SELECT USERNAME FROM studentsTable WHERE USERNAME = ? AND PASSWORD = ?");
stmt.setString(1, username);
stmt.setString(2, password);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
// valid credentials
} else {
// invalid credentials
}
rs.close();
stmt.close();
Depending on the nature of the site another good practice is to display the same generic message to the user on failed regardless of whether it was the username (or email address) or password that was incorrect. An example message is "Invalid username or password." The benefit to this is that it helps prevent username harvesting as the attacker would not be able to tell from the error message that the username is valid. For some sites this matters more than others and a site where the usernames are already public would not benefit as much as other harvesting methods are available.