i've been trying to make this piece of code work work for a while now but seems like it wont. My User inputs Username and Password and then the program compares it to the DB. However it displays Invalid Credentials even though when i output the password it displays the exact same i've input.Just a few points, i know some of you are going to point on things like Using a seperate class for Connection, Check against username for password instead of using Select *, use hashings and all. But right now at the moment i just need to get this code work. Only after that i will be able to work on other aspects to ENHANCE its efficiency. Thank you all in advance.:)
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
// TODO add your handling code here:
Username1 = "jTextField1.getText()";
Password1 = "jPassword1Field2.geText()";
try
{
Class.forName("com.mysql.jdbc.Driver").newInstance();
String url = "jdbc:mysql://localhost:3306/";
String dbName = "VideoSystem" ;
String userName = "root";
String passWord = "**mypassword**";
Connection conn = DriverManager.getConnection(url+dbName, userName, passWord);
Statement st = conn.createStatement();
String sql = ("SELECT * FROM Identification");
ResultSet rs = st.executeQuery(sql);
while(rs.next())
{
password = rs.getString("Password");
if( Password1.equals(password))
{
MenuSelection obj1 = new MenuSelection();
obj1.setVisible(true);
}
else
{
JOptionPane.showMessageDialog(null, "Invalid Credentials", "System Message", JOptionPane.INFORMATION_MESSAGE);
}
}
conn.close();
}
catch (Exception e)
{
System.err.println("Got an exception! ");
System.err.println(e.getMessage());
}
}
Those two lines:
Username1 = "jTextField1.getText()";
Password1 = "jPassword1Field2.geText()";
They are string literals, so unless your password is literally jPassword1Field2.geText(), there's not gonna be a match. I think you meant:
Username1 = jTextField1.getText();
Password1 = jPassword1Field2.getText();
Note however, that JPasswordField.getText() is deprecated since Java 2. You should use getPassword() instead:
Password1 = new String(jPassword1Field2.getPassword());
The documentation justifies the deprecation of getText() with "security reasons" that I can't claim to understand, but you still shouldn't use deprecated parts of the API.
And I know you some of the below already and none of that is part of your question, but I really suggest that you
Check against the username. It should be obvious why.
Hash passwords. Always.
Only fetch what you need, mostly for performance reasons. Usually the best way is to use a WHERE clause in SQL (that brings the need to sanitize your input, but you should do that anyway) and building a list of columns instead of fetching *.
Use backticks for database/table/column names in SQL to avoid things like accidentally using a keyword as table/column name or so.
Applying the above, I suggest the following query (assuming the name field is called Username):
PreparedStatement st = conn.prepareStatement("SELECT `Password` FROM `Identification` WHERE `Username` = ?");
st.setString(1, Username1);
ResultSet rs = st.executeQuery();
Related
I'm currently creating the login functionality of a java web application just using java and JDBC. What built in java libraries are there to make the authentication process easier. I am able to query my PostgreSQL database and retrieve user information such as their password and username but I do not want to store it in plain text.Any tips would be great and o yeah I'm not using spring, which I see there is plenty for.
Generally, password matching is done by storing a one-way hash of the password, instead of storing the password itself as plain text. When someone tries to log in, your application generates a one-way hash of the password the user has entered, and checks whether it matches any of the hashes stored in the database.
Hashing is done with the MessageDigest class:
byte[] passwordBytes = password.getBytes(StandardCharsets.UTF_8);
byte[] passwordHash;
try {
passwordHash = MessageDigest.getInstance("SHA-256").dist(passwordBytes);
} catch (NoSuchAlgorithmException e) {
// It should be impossible to get here, since SHA-256 is
// a standard algorithm supported by all Java runtimes.
throw new RuntimeException(e);
}
The password column in your database should be defined as a binary type, like VARBINARY. Then you can store the bytes directly:
try (PreparedStatement statement =
connection.prepareStatement(
"INSERT INTO users (name, passwordhash) VALUES (?, ?)")) {
statement.setString(1, name);
statement.setBytes(2, passwordHash);
statement.executeUpdate();
}
You can check whether a login attempt matches in a similar manner:
try (PreparedStatement statement =
connection.prepareStatement(
"SELECT name, email, phone FROM users"
+ " WHERE name = ? AND passwordHash = ?")) {
statement.setString(1, enteredName);
statement.setBytes(2, enteredPasswordHash);
ResultSet results = statement.executeQuery();
if (!results.next()) {
throw new MyAppInvalidLoginException("No matching login found.");
}
String name = results.getString(1);
String email = results.getString(2);
String phone = results.getString(3);
}
I’m not a security expert, so I will leave it to people with expertise in that area to comment on whether SHA-256 is sufficiently secure for general needs.
I try duplicate the entries in the username column but the result is always in the else statement which is the data is successfully inserted into the table which should not be duplicated based on the if statement. By the way String value1=username1.getText();.
here's the code:
String sq = "SELECT username FROM login where username = '"+value1+"'";
if (sq.equals(value1)){
JOptionPane.showMessageDialog(null,"username is already existed! please
create new username.");
}
else{
int k=st.executeUpdate("insert into
login(username,password,firstname,lastname,address,contactno)
values('"+value1+"','"+value2+"','"+value3+"','"+value4+"',
'"+value5+"','"+value6+"')");
JOptionPane.showMessageDialog(null,"Data is successfully saved");
}
You just create the SQL string and never run it (instead, you compare it to the username, which will always be false).
You should actually execute it and check the result.
E.g. (error handling and resource cleanup omitted for brevity's sake):
Connection conn = // Connect to the database...
PreparedStatement ps =
conn.prepareStatement("SELECT username FROM login where username = ?";
ps.setString(1, value1);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
JOptionPane.showMessageDialog
(null,"username is already existed! please create new username.");
}
sq will never be equal to value1 if you just assign it to a complete SELECT statement:
String sq = "SELECT username FROM login where username = '"+value1+"'";
What you are missing is the DB request for your sq String.
sq contains the query (sql code)
String sq = "SELECT username FROM login where username = '"+value1+"'";
value1 contains the username value (for example "user1"). So
sq.equals(value1)
will be always false
"SELECT username FROM login where username = '"+value1+"'" != value1
String Basics:
String sq = "Something in double quotes"
Assigns Something to sq.
And
String value1=username1.getText();
May get some other string, lets say for example "root"
sq.equals(value1)
Now String class equals() method check content of both Strings(sq and value1).
And if not equal returns false, which happens in your case.
Now how to achieve your goal? people already answered that check it.
I recommend to study yourself
I've made a program which is getting data from database and then authorizing, but the problem is only the last record is correct - logging in is succesful.
public class Test {
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost:3306/uzytkownicy";
static final String USER = "root";
static final String PASS = "";
public static void main(String[] args) throws SQLException, ClassNotFoundException {
System.out.print("login: ");
Scanner zm1= new Scanner(System.in);
String name = zm1.next();
System.out.print("pass: ");
Scanner zm2 = new Scanner(System.in);
String password = zm2.next();
try{
Class.forName("com.mysql.jdbc.Driver");
System.out.println("Connecting...");
Connection conn = DriverManager.getConnection(DB_URL,USER,PASS);
Statement stmt = conn.createStatement();
String sql = "SELECT logins, passwords FROM users";
ResultSet rs = stmt.executeQuery(sql);
String databasePassword = null;
String databaseUsername = null;
while (rs.next()) {
databaseUsername = rs.getString("logins");
databasePassword = rs.getString("passwords");
}
if (name.equals(databaseUsername) && password.equals(databasePassword)) {
System.out.println("Logged in!");
}
else {
System.out.println("Bad Pass/Login");
}
rs.close();
stmt.close();
conn.close();
}
catch(SQLException se){
se.printStackTrace();
}
}
}
If I'm understanding what you're trying to do (which I may not be), your problem is that the comparison of username and password is outside the while loop, so your:
while (rs.next())
just loops through the entire result set, so when the while loop ends, databaseUsername and databasePassword will be set to the values from the last row read.
Instead, move the comparison inside the loop and set a flag (defaulting to false) and break out of the loop if the correct username and password is found, then use that flag to determine what to print.
Also, you might want to read up on parameterized queries. You can actually have the database do all the work for you by using a PreparedStatement and making your query:
SELECT 1 from users where logins = ? and passwords = ?;
If the result set contains anything, then the user entered a valid username and password, otherwise they didn't. The question marks in the query would be set to name and password using the set* methods of PreparedStatement.
Another note--storing plaintext passwords is a horrible idea. If the table storing the passwords is exposed (through various attacks or just a disgruntled employee stealing it), then everyone has all your users' passwords. Eek! You might argue that you'll take steps to prevent that, but from a security perspective, it's best to assume someday the table will be compromised, and do everything you can to ensure that it's not too harmful.
I'm practicing programming using Java and MySQL using NetBeans IDE. I can log-in my application using the code below. But if I will encrypt my password using the aes_encrypt feature of MySQL, I don't know how to decrypt it. I know there is aes_decrypt but I had a hard time with the syntax.
private void btnLoginActionPerformed(java.awt.event.ActionEvent evt) {
if(lblUsername.getText().length()==0) // Checking for empty field
JOptionPane.showMessageDialog(null, "Empty fields detected ! Please fill up all fields");
else if(password.getPassword().length==0) // Checking for empty field
JOptionPane.showMessageDialog(null, "Empty fields detected ! Please fill up all fields");
else{
String user = lblUsername.getText(); // Collecting the input
char[] pass = password.getPassword();
String pwd = String.copyValueOf(pass); // converting from array to string
if(validate_login(user,pwd)){
JOptionPane.showMessageDialog(null, "Correct Login Credentials");
MainStudentRecord mainstudentrecord = new MainStudentRecord();
mainstudentrecord.setVisible(true);
this.dispose();
}
else{
JOptionPane.showMessageDialog(null, "Incorrect Login Credentials");
lblUsername.setText("");
password.setText("");
}
}
}
private boolean validate_login(String username,String password) {
try{
Class.forName("com.mysql.jdbc.Driver"); // MySQL database connection
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/studentrecord","neil","basabe");
PreparedStatement pst = conn.prepareStatement("Select * from user where username=? and password=?");
pst.setString(1, username);
pst.setString(2, password);
ResultSet rs = pst.executeQuery();
if(rs.next())
return true;
else
return false;
}
catch(Exception e){
e.printStackTrace();
return false;
}
}
Here is my table definition:
username varchar(16)
password varchar(16)
to:
username varchar(16)
password blob --------- this is for me to use aes_encrypt
I know this is the part that I should edit:
PreparedStatement pst = conn.prepareStatement("Select * from user where username=? and password=?");
to:
PreparedStatement pst = conn.prepareStatement("Select * from user where username=? and password=_______this is the confusing part_________");
Please help!
There are multiple issues here. I'll address the one that you have identified first:
You have transformed the password in some way to store it in the database. Perform the same transformation on it to determine if it is stored there rather than trying to reverse the transformation on the data you have stored.
The transformation you have used is a reversible encryption. You should store your passwords non-reversible hash (and salt) of the (salted) password. It is a good idea for this to be a computationally expensive operation, considering both time and space. Using something like scrypt to generate the password hashes helps to meet that requirement.
How to store passwords is a topic that I won't go in to any further. However, if it is possible not to store password data at all and use a third party (think all of those websites that allow you to log in with google/facebook/twitter/etc ... just like this one does), do that, they're much more likely than you to get secure password storage correct.
How do I validate a certain email and password while an user logs in?
protected void doPost(HttpServletRequest request, HttpServletResponse res) throws IOException, ServletException {
String email=request.getParameter("email");
String pass=request.getParameter("pass");
OutputStream out = res.getOutputStream();
try{
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:8080/college", "root", "root");
Statement st=con.createStatement();
String strSQL = "SELECT email,password FROM student";
How do I continue after the SELECT statement? I would prefer using the if...else statement to do the validation.
First close all connection resources properly - use a Java 7 try-with-resources.
Here is an simple example:
final String email = request.getParameter("email");
final String pass = request.getParameter("pass");
try (final Connection con = DriverManager.getConnection("jdbc:mysql://localhost:8080/student", "root", "root");
final PreparedStatement statement = con.prepareStatement("SELECT COUNT(*) AS count FROM student WHERE email=? AND password=?");) {
statement.setString(1, email);
statement.setString(2, pass);
try (final ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
final int rows = resultSet.getInt("count");
if (rows > 1) {
throw new IllegalStateException("More than one row returned!");
}
boolean validUser = rows == 1;
}
}
}
But really you should hash passwords in the database. Use something like jBcrypt. Your code would then look like:
final String email = request.getParameter("email");
final String pass = request.getParameter("pass");
try (final Connection con = DriverManager.getConnection("jdbc:mysql://localhost:8080/student", "root", "root");
final PreparedStatement statement = con.prepareStatement("SELECT pass FROM student WHERE email=?");) {
statement.setString(1, email);
statement.setString(2, pass);
try (final ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
final String hash = resultSet.getString("pass");
final boolean valid = BCrypt.checkpw(pass, hash);
}
}
}
Obviously you need to add error checking if there are no rows returned from the query. You also need to check that only one row is returned. But I leave that as an exercise.
you can use if, if you like. Use the input as your where statement and then check to see if there is a match, error or null, then execute whatever you want it to do.
You can use email and password in the SQL statement itself. like:
SELECT email, password from student where email = ? and password = ?
prepare above statement and bind the parameters.
This way validation will be done on the DB and you just need to check the result count (which has to be 1). You should have index on email column to have better SQL performance.
Do you relay need to fetch all students?
PreparedStatement st = con.prepareStatement("SELECT count(*) FROM student WHERE email=? AND password=?");
st.setString(1, email);
st.setString(2, pass);
ResultSet rs = st.executeQuery();
rs.next();
int count = rs.getInt(1);
if (count == 1) {
// password and email are correct
}
For this answer, I'll assume that by "validate email and password", what you mean is you want to authenticate the user based on their email address and a password. And not that you want to check whether the email address is a real email address.
So, the first thing you need to do is encrypt the passwords in your database, using a hash algorithm and a random salt. You record the salt alongside the hashed password.
Next thing is, when the user logs in, you look up the salt for that user, and you perform the same hash with the salt. Then you compare the result of that with the previously saved password hash, and if they're the same, then the passwords were the same.
It's important that the salt be random and different for every user.
Plenty of reading to be found on the above terms on the Internets.
Once you've done that, you should also apply the very sensible suggestions in other answers to only select the user you want, and handle your resources correctly.
WARNING I am not an expert on security, and neither are you. If you're implementing a log-in system for an exercise, fine. If it's for the real world, use something that's been written by someone who knows what they're doing.