How to validate user email from the MySQL database? - java

There is a registration form on my web application. What I want is, when a user submits the form, validation should be done to check if the email id which the user entered already exists or not in the database.
And accordingly, if it exists then a message like in a snackbar should appear saying, the email id already exists. If it's a new email, then it will redirect to the success page.
Following is my checkData method where I am just checking if when I enter the email id on the form, it exists or not, but the ouput is always "value not found".
public void checkData() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/dbname?autoReconnect=true&useSSL=FALSE", "root", "pwd");
st = con.createStatement();
String query1 = "select email from users where email='" +email99+ "'";
ResultSet rs = st.executeQuery(query1);
if(rs.next()) {
System.out.println("Success");
}
else {
System.out.println("Value not found");
}
rs.close();
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println(e.getMessage());
}
}
Note:- My main concern is email validation.
Thank you

For Email validation
you have to set email column as unique in you table.
when ever you are trying to insert new user, SQL will throw an constraint violation exception if email already exists. you can use that error also for error handling
generally update will take more time compared to get operation So the best method is..
First you have to check is there any row exist with this email ID
String sql = "select email from users where email= ? ";
PreparedStatement prepStmt = conn.prepareStatement(sql);
prepStmt.setString(1, "emailId");
ResultSet rs = prepStmt.executeQuery();
if (rs.next()) {
System.out.println("Row with email found");
} else {
// you can write update code here
}

For Unique Email validation, there are two methods:
Method 1:
The first one is to execute the select query and check it, which is not recommended as a solution.
PreparedStatement statement = connection.prepareStatement("select email from users where email= ?");
statement.setString(1, email99);
ResultSet resultSet = statement.executeQuery();
if (resultSet.next()) {
System.out.println("Row with email found");
} else {
// you can write update code here
}
Method 2:
on the DB level, make the email column unique. so whenever a new record is inserted. DB is responsible for checking the unique email address and throw the error. Use the error to display it on the front end.
cheers!!

Method1:
The simplest method is using unique index on column email.
You can not using the solution which looks up email firstly and insert email. Suppose that there are two users submit the email some#email.com. And there does't have the email in your DB.
Both users will get res.next() false, and you will insert two rows with the same email to DB.
If you use the unique index, you will get Exception if there already has the email. You can catch the Exception and return the "duplicate email" message.
See the question catch duplicate exception
If you use Mysql, maybe you can use the ON DUPLICATE KEY.
Method2:
There has a more complicated solution.
If you can not use the unique index, then you can consider this.
You can use the Lock. If you work on distributed system, you should use the distributed lock. You should lock the email. If the thread get the lock, you can check whether there has the target email and then insert into DB.
But if your system just run on one JVM, you can try:
syschronized(email.intern()) {
// check the email whether exists
// if not, insert it.
}
In this case, you will suffer from the large String pool which will affect your GC pause and waste memory.
In fact you can use double-check to optimize the performance. It looks like
emailInDB = fetchEmailFromDB(email);
if (emailInDB == null) {
lock(email);
emailInDB = fetchEmailFromDB(email);
if(emailInDB == null) {
insertIntoDB(email)
} else {
return "the email already exists";
}
} else {
return "the email already exists";
}

Related

Java Login Method with Database Connection failing to complete

Searched for an answer to this but can't find anything similar. Checked the questions which may already have my answer as well but again no solution.
So first of all, here is the code which doesn't complete:
Class.forName(DRIVER);
Connection connection = DriverManager.getConnection(URL, USER,
PASS);
Statement statement = connection.createStatement();
e = email.getText();
p = password.getText();
String SQL = "SELECT email, password FROM healthcareProfessional WHERE email = '" + e
+ "' AND password = '" + p + "';";
ResultSet resultSet = statement.executeQuery(SQL);
while (resultSet.next()) {
if (email.getText().equals(resultSet.getString("email"))
&& password.getText().equals(resultSet.getString("password"))) {
Main.applyHomescreenLayout();
} else if (email.getText().equals("") || password.getText().equals("")) {
errorMessage.setText("Incorrect Email.");
errorMessage.setTextFill(Color.RED);
FadeTransition fadeTransition = new FadeTransition(Duration.millis(3000.0), errorMessage);
fadeTransition.setFromValue(3000.0);
fadeTransition.setToValue(0.0);
fadeTransition.playFromStart();
}
}
Everything here works fine provided I enter valid login credentials. However, if I leave the email or password blank and try to log in, no message is displayed and I can't understand why. Can anyone point me in the right direction?
Also, if I remove the connection the below code works perfectly and the message is displayed.
if (email.getText().equals("") || password.getText().equals("")) {
errorMessage.setText("Incorrect Email or Password.");
errorMessage.setTextFill(Color.RED);
FadeTransition fadeTransition = new FadeTransition(Duration.millis(3000.0), errorMessage);
fadeTransition.setFromValue(3000.0);
fadeTransition.setToValue(0.0);
fadeTransition.playFromStart();
}
I have also tried closing the resultset, statement and connection within the if and else if statements, replacing the .equals("") with .isEmpty(), and using separate resultsets, none of which worked.
First of all this check must be before checking Database, i.e. before execution of DB query to check for user credentials.
if (email.getText().equals("") || password.getText().equals("")) {
errorMessage.setText("Incorrect Email.");
errorMessage.setTextFill(Color.RED);
FadeTransition fadeTransition = new FadeTransition(Duration.millis(3000.0), errorMessage);
fadeTransition.setFromValue(3000.0);
fadeTransition.setToValue(0.0);
fadeTransition.playFromStart();
}
You must not allow anyone with no password or no email id to sniff your database check.
Secondly but your DB connection in try catch block and in finally block release all connection objects,statement objects.
Thirdly use prepared statement to protect your system from sql injections.It is not good practice to create query in this way.
https://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html
Do you get any message when the email and password are not blank but does not match?
It seems that if there is no matching combination the resultSet will be empty and next() will always evaluate as false, completely skipping the while loop.
What I would do (no compiler here, so the code can have mistakes) is:
ResultSet resultSet = statement.executeQuery(SQL);
if (resultSet.next()) {
//No need to re-validate
Main.applyHomescreenLayout();
} else {
//no email|password combination found on database
errorMessage.setText("Incorrect Email.");
errorMessage.setTextFill(Color.RED);
FadeTransition fadeTransition = new FadeTransition(Duration.millis(3000.0), errorMessage);
fadeTransition.setFromValue(3000.0);
fadeTransition.setToValue(0.0);
fadeTransition.playFromStart();
}
This was said before but is always good to be reinforced: take a look at prepared statements to avoid sql injections.
Your else block is essentially unreachable.
Your SQL statement selects only rows in the database table for which the database email field is equal to the text in the email text field, and for which the database password field is equal to the text in the password text field (or PasswordField, presumably).
So if the user leaves either email or password blank, it will select only rows from the database for which email is blank or password is blank, respectively. In that case, for any row in the result set, the test
if (email.getText().equals(resultSet.getString("email"))
&& password.getText().equals(resultSet.getString("password")))
will still evaluate to true, so you won't reach the else block. If there are no such rows in the database table, then you simply get an empty result set and your while loop iterates zero times, so you won't reach the else block (or even the if block) under those conditions either.

Java - Cannot return/access ResultSet from MySQL StoredProcedure

I have users table in MySQL and I created a stored procedure so that when get username and password from swing textfields passed them into stored procedure and learn if is there exist that user to login, but I can not get resultset actually in phpMyAdmin stored procedure work properly but in netbeans can not get resultset and runtime never stop in console , running always.
I do not think there is a problem in my code somewhere else because it is so simple code.
Here is my stored procedure in MySQL
SELECT * FROM `users` WHERE `users`.`E-Mail` = #p0 AND `users`.`Password` = #p1
it takes two parameter varchar and I tried before those as a text
Here is the specific part of my java code
public void loginPass(String email, String password){
try {
DriverManager.registerDriver((Driver) Class.forName("com.mysql.jdbc.Driver").newInstance());
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/askdocdb","root","");
CallableStatement mystatement = connection.prepareCall("{CALL sp_Login (?, ?)}");
mystatement.setString(1, email);
mystatement.setString(2, password);
// mystatement.setString("#p0", email);
// mystatement.setString("#p1", password);
boolean situation = mystatement.execute();
System.out.println(situation);
// resultset = mystatement.executeQuery();
resultset = mystatement.getResultSet();
String res = resultset.getString(2);
System.out.println(res);
// resultset = mystatement.executeQuery();
while(resultset.next()){
System.out.println("asdsad");
}
resultset.close();
} catch (Exception e) {
}
}
The reason of comment lines, I tried any possible combination of syntax
situation returns true
res does not return
and can not enter into while statement
Thank you for your support and comments already now.
It's difficult to say what exactly is wrong with your code as there are quite a few possible points for failure if you choose to use a stored procedure for this simple task (incorrect syntax in the procedure, problems with getting the return value over JDBC, etc). I would simply run the SQL query over JDBC for checking the credentials:
public void registerDriver() {
try {
DriverManager.registerDriver((Driver) Class.forName(
"com.mysql.jdbc.Driver").newInstance());
} catch (InstantiationException | IllegalAccessException
| ClassNotFoundException | SQLException e) {
throw new RuntimeException("Could not register MySQL driver!", e);
}
}
public boolean checkLogin(String email, String password) {
try (Connection connection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/askdocdb", "root", "");
PreparedStatement ps = connection
.prepareStatement("SELECT 1 FROM users WHERE "
+ "E-Mail = ? AND Password = ?")) {
ps.setString(1, email);
ps.setString(2, password);
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
return true; // username and password match
} else {
return false; // no row returned, i.e. no match
}
}
} catch (SQLException e) {
throw new RuntimeException(
"Error while checking user credentials!", e);
}
}
What was changed:
JDBC driver registration has been extracted into a separate method (registerDriver()), which you only need to call once (e.g. after the program has started), not each time you check for credentials.
Resources such as Connection, PreparedStatement and ResultSet are now being closed properly (even if an exception is thrown) because they are declared through the try-with-resources statement.
The method now returns a boolean that corresponds to whether the credentials were valid or not, making it easier to use from calling code.
Exceptions that cannot be handled (e.g. SQLException) are rethrown as RuntimeExceptions (instead of just swallowing them in an empty catch block).
Basically, when an SQLException is thrown, either there is a programming error in the code (invalid query syntax) or something severely wrong with the database. In either case, the only option is usually to halt your program. You can declare throws SQLException in the method signature if you'd want to handle the situation in the calling method instead.
Finally, it needs to be mentioned that you should never store passwords in the database as plain text, to avoid anyone with read access to the db to login as an arbitrary user. Instead, you should store password hashes, or even better, salted hashes. More on this e.g. in Best way to store password in database.

I'm trying to Validate username and password

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");}

How to get result size from an SQL query and check size

Hi I'm trying to write a piece of code for a simple verification method as part of a MVC.
At present the SQL is not written as a prepared statement so obviously it is at risk to a SQL injection so any help in regards to writing the SQL as a prepared statement would be really helpful.
The method which is in the User model.
public boolean getInfo() {
try {
DBAccess dbAccess = new DBAccess();
String sql = "SELECT username, password FROM owner WHERE username = '" + this.username
+ "'AND password = '" + this.password + "';";
dbAccess.close();dbAccess.executeQuery(sql);
dbAccess.close();
return true;
} catch (Exception e) {
return false;
}
}
I want to get the size of the result set which is generated by the SQL query and if the size of it is 1 return true else it's false.
If you need more info on the rest of the MVC just post and I'll get it up here.
Just return the result of ResultSet#next(), assuming that there's an UNIQUE constraint on the username. It returns false if there is no next record.
Here's a concrete kickoff example, slightly rewritten to fix potential SQL injection attack hole, resource leaking and threadsafety problems as shown so far in your code. Also, the altered SQL query should force you to MD5-hash the passwords before saving in DB (you don't want to store passwords plaintext in DB).
public boolean exist(String username, String password) throws SQLException {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
boolean exist = false;
try {
connection = database.getConnection();
statement = connection.prepareStatement("SELECT id FROM owner WHERE username = ? AND password = MD5(?)");
statement.setString(1, username);
statement.setString(2, password);
resultSet = statement.executeQuery();
exist = resultSet.next();
} finally {
if (resultSet != null) try { resultSet.close(); } catch (SQLException ignore) {}
if (statement != null) try { statement.close(); } catch (SQLException ignore) {}
if (connection != null) try { connection.close(); } catch (SQLException ignore) {}
}
return exist;
}
Rather select the fields username and password, you could select the count of them and then reference that value.
So your SQL query would be:
SELECT count(*) FROM owner WHERE username = '" + this.username
+ "'AND password = '" + this.password + "';
That would return the number of matched records, where if number is greater than 0, or equals one, validate them.
Without knowing the details of your DBAccess class, we can't tell you how to do this. I'm guessing it returns a List (but it's a guess, nothing more). If that's the case, you could check the size of the List via list.size() , or see if it returned at least 1 result with !list.isEmpty(). Of course, if it's not a list then this won't work.
And you definitely need to switch to prepared statements. For an example, see this SO post.
Side note: if this method is returning a boolean indicating whether a user exists, it shouldn't be called getInfo()! Something like userExists() would make more sense.
For your question about preventing sql injection, and if you want to start getting your feet wet with an "ORM like" library, you could use myibatis to create prepared statements. Myibatis is a data mapper which you can create a relatively simple ORM from. As you get more brave, you could move to hibernate or JPA.
http://www.mybatis.org/

why it checks just the last row of sql?

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.

Categories