Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
OK so I am trying to create user authentication for a little Java project of mine and I've run into a bit of a road block.
I have a table called user_info with 3 columns; id, user and password.
I realized that I should probably have some form of encryption, so I used Java's MessageDigest to encrypt the password with SHA1. Since I don't yet have a website for people to register (and have PHP enter the encrypted PW into the database), I simply encrypted a test password and replaced the unencrypted password in the database with the encrypted one.
For example, a user with username test and password test has an encrypted password of:
895df4f75b316de68d167ed2e83adb0bedbbde17
So my database has an entry with id 0, user test and password 895df4f75b316de68d167ed2e83adb0bedbbde17.
Now my Java code to check if the person provided valid details had no issue until I started using encrypted passwords.
Here is the login code for my Java application:
public int doLogin(String username, String pass) {
EncryptionHandler e = new EncryptionHandler();
String userToLogIn = username;
String userToLogInPassword = pass;
try {
String fixedUser = prepString(userToLogIn);
String fixedPass = e.doEncryptPassword(prepString(userToLogInPassword));
System.out.println(fixedPass);
con = DriverManager.getConnection(url, user, password);
st = con.createStatement();
rs = st.executeQuery("SELECT * FROM `user_info` WHERE `user` = " + fixedUser + " AND `password` = " + fixedPass);
if (rs.next()) {
//System.out.println("ID: " + rs.getString(1) + ", USER: " + rs.getString(2) + ", PASSWORD: " + rs.getString(3));
return 1;
} else {
System.out.println("Username or password is invalid!");
return 0;
}
} catch (SQLException ex) {
System.out.println(ex.getMessage());
} finally {
try {
if (rs != null) {
rs.close();
}
if (st != null) {
st.close();
}
if (con != null) {
con.close();
}
} catch (SQLException ex) {
}
}
return 0;
}
private String prepString(String s) {
return new StringBuilder().append("'").append(s).append("'").toString();
}
and in case it's needed, my encryption method:
public String doEncryptPassword(String s) {
MessageDigest sha1;
try {
sha1 = MessageDigest.getInstance("SHA1");
byte[] digest = sha1.digest((s).getBytes());
return bytes2String(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return s;
}
private static String bytes2String(byte[] bytes) {
StringBuilder string = new StringBuilder();
for (byte b : bytes) {
String hexString = Integer.toHexString(0x00FF & b);
string.append(hexString.length() == 1 ? "0" + hexString : hexString);
}
return string.toString();
}
Again, using unencrypted passwords works just fine, but as soon as I encrypt the password I get the unknown column error. In this example (user test, password test), passing the unencrypted password receives no error, but using the encrypted password 895df4f75b316de68d167ed2e83adb0bedbbde17 provides me the error:
Unknown column '895df4f75b316de68d167ed2e83adb0bedbbde17' in 'where clause'
Ignoring that this isn't encryption, you have invalid SQL because of quoting problems. As #Leigh notes in the comments, you put quotes at the beginning and end of your password string ... then hash it. Your quotes are now dearly departed.
Of course you should never create SQL like this in the first place. Use prepared statements -> Oracle Prepared Statements Tutorial
Get rid of any of your own home-grown string quoting then simply do:
String sqlString = "SELECT * FROM user_info WHERE user = ? AND password = ?";
PreparedStatement ps = con.prepareStatement(sqlString);
ps.setString(1, username);
ps.setString(2, hashedPassword);
ResultSet rs = ps.executeQuery();
You need to do your prepString thingy as well for the password:
String fixedPass = prepString(e.doEncryptPassword(userToLogInPassword));
But it isn't a good idea to build statements this way.
Use prepared statements.
Related
I have built a function to hash the users password when they register using my java application. I am not sure how I should go about trying to verify their login since the password stored is going to be hashed.
I have tried making a function, that takes the entered password and hashes it and then compares the hash to the one in the database but, this didn't work since each time the hashing function is run on a password (String) the result is never the same. I am not sure how to verify the users password on login. Below I have provided:
Login button code
Generating secure password using salt function
Verification function
Login button code:
try {
// Get password from database and verify login
String slt = passwordUtils.getSalt(100);
Connection con = connectDB.getConnectionUser();
Statement stmt = null;
String sql = "SELECT * FROM USER where userEmail=?";
PreparedStatement pst = con.prepareStatement(sql);
pst.setString(1, userEmail.getText());
ResultSet rs = pst.executeQuery();
String fromDatabase = rs.getString(3); //get the password stored in database (hashed version)
String enteredPassword = String.valueOf(userPassword.getPassword()); //get entered password
if(rs.next()){
if(passwordUtils.verifyUserPassword(enteredPassword, fromDatabase, slt)){
JOptionPane.showMessageDialog(null, "Login details are correct. Welcome!");
con.close();
} else {
JOptionPane.showMessageDialog(null, "Invalid Log in details, try again.");
con.close();
}
}
} catch (SQLException ex) {
Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, ex);
}
Generate secure password function
public static String generateSecurePassword(String password, String salt){
String returnValue = null;
System.out.println("password supplied is: " + password + "salt added: " + salt);
System.out.println("");
byte[] securePassword = hash(password.toCharArray(), salt.getBytes());
System.out.println("");
System.out.println("secure pwd byte[]: " + securePassword);
System.out.println("");
returnValue = Base64.getEncoder().encodeToString(securePassword);
System.out.println("");
System.out.println("secure pwd converted " + returnValue);
return returnValue;
}
Verify login function
public static boolean verifyUserPassword(String providedPassword, String securedPassword, String salt){
boolean returnValue = false;
// generate new secure password with same salt
String newSecurePassword = generateSecurePassword(providedPassword, salt); //generate secure password using salt
//check to see if both passwords are the same
returnValue = newSecurePassword.equalsIgnoreCase(securedPassword);
System.out.println("Hashed password: " + securedPassword);
System.out.println("Verify hash: "+ newSecurePassword);
return returnValue;
}
Salting function
public static String getSalt(int length){;
StringBuilder returnValue = new StringBuilder(length);
for(int i = 0; i < length; i++){
returnValue.append(ALPHABET.charAt(RANDOM.nextInt(ALPHABET.length())));
}
System.out.println("final salt generated: " + returnValue);
return new String(returnValue);
}
Hashing function:
public static byte[] hash(char[] password, byte[] salt){
PBEKeySpec spec = new PBEKeySpec(password, salt, ITERATIONS, KEY_LENGTH);
Arrays.fill(password, Character.MIN_VALUE);
try{
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
System.out.println("skf return to secure password call: " + skf.generateSecret(spec).getEncoded());
return skf.generateSecret(spec).getEncoded();
} catch (NoSuchAlgorithmException | InvalidKeySpecException e){
throw new AssertionError("Error while hashing a password: " + e.getMessage(), e);
} finally {
spec.clearPassword();
System.gc();
}
}
After reading taking on board the feedback received under this post. I managed to solve the issue.
I created another column in the database which was storing Users and named the column "saltPassword". This would store the salt used on the password, which can later be retrieved to check password validation.
After storing the hashed password and the salt used in the database when a user registers. It became quite simple to perform password verification.
public boolean verifyPassword(String providedPassword, String fromdatabase, String passwordSalt){
boolean isValid = false;
String generate = passwordUtils.generateSecurePassword(providedPassword, passwordSalt);
isValid = generate.equals(fromdatabase);
return isValid;
}
This function was used for password verification.
It takes the password entered by the user in the password field, the password currently stored in the database (hashed) and the salt used for the password.
It then generates a salted password using the entered password along with the same salt used for the original password in the database. This should produce the same hashed password in the database. We then check that this is the case by applying .equals(fromdatabase) and checking if it's the same as the one in the database. If this is true, then the password is correct and the user can be logged in.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
Its working fine with correct user and password,but when i use wrong user and password, it does not work.if and else-if working but else statement is not working.
here is my code :
String user = textField.getText().trim();
String pwd = new String(passwordField.getPassword()).trim();
String type = (String) comboBox.getSelectedItem();
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/test", "root", "root");
String sql = "select * from userauthentication where username=? and password=? and type=?";
ps = con.prepareStatement(sql);
ps.setString(1, user);
ps.setString(2, pwd);
ps.setString(3, type);
rs = ps.executeQuery();
while (rs.next()) {
String uname = rs.getString("username");
String pass = rs.getString("password");
if ((user.equals(uname) && pwd.equals(pass))) {
if (type.equals(Admin_Type)) {
JOptionPane.showMessageDialog(null,
" This is from admin message.");
// rs.close();
} else if (type.equals(User_Type)) {
JOptionPane.showMessageDialog(null,
"This is from user message.");
// rs.close();
}
else {
JOptionPane.showMessageDialog(null,
"No user found!.");
}
} else {
JOptionPane.showMessageDialog(null,
"Something going wrong.please try again.");
}
}
} catch (Exception e) {
System.out.println(e);
}
Add below condition before the while loop
if (!rs.isBeforeFirst() ) {
//show error message here.
System.out.println("No data");
}
A possible fix is use an if statement instead of a while loop in order to check that you retreive a valid user.
Consider that the resultset probably wont retrive any data so in that case the statements after the while loop will not be executed.
Here is an alternative
if (rs.next()) {
if (type.equals(Admin_Type)) {
message = " This is from admin message.";
} else if (type.equals(User_Type)) {
message = " This is from user message.";
} else {
message = "Invalid Type user!.";
}
} else {
message ="Something going wrong.please try again.";
}
JOptionPane.showMessageDialog(null,message);
Also consider to use another authentication method based on frameworks, avoid to create your own authentication method. This sample is good for educational prupose to practice how to read fields from database using a ResultSet and how to display message throught JOptionPane.
Regards
String sSQL = "select RFC,Contraseña from Administradores where RFC='" + txtUsuario.getText() + "' and Contraseña='" + txtContrasena.getText() + "'";
String[] registros = new String[2];
Try {
conect();
conexion = DriverManager.getConnection("jdbc:sqlite:" + base);
Statement stat = conexion.createStatement();
ResultSet rs = stat.executeQuery(sSQL);
while (rs.next()) {
registros[0] = rs.getString("RFC");
registros[1] = rs.getString("Contraseña");
}
stat.close();
conexion.close();
} catch (SQLException ex)
{
JOptionPane.showMessageDialog(null,"DB connection error");
}
if ((txtContrasena.getText().equals(registros[1])) || (txtUsuario.getText().equals(registros[0]))) {
JOptionPane.showMessageDialog(null, "Access Granted");
Escoger variable = new Escoger();
variable.setVisible(true);
dispose();
} else {
if (txtContrasena.getText() != (registros[1])) {
JOptionPane.showMessageDialog(null, "Incorrect password");
}
}
This...
String sSQL = "select RFC,Contraseña from Administradores where RFC='" +
txtUsuario.getText() + "' and Contraseña='" +
txtContrasena.getText() + "'";
Would automatically suggest it is. Anything that is input into the txtUsuario and txtContrasena could contain valid SQL code that could be executed by the SQL engine of the database.
You should be using:
String sSQL = "select RFC,Contraseña from Administradores where RFC=? and Contraseña=?";
You will then need to change...
Statement stat = conexion.createStatement();
To
PreparedStatement stat = conexion.preapreStatement(sSQL);
stat.bindString(1, txtUsuario.getText());
stat.bindString(2, txtContrasena.getText());
Take a look at Using Prepared Statements for more details
Further, you should never store a password in the database. You should store a hashed version of the password in the database, and to check the password you hash what you're given (securely, https if via web) and compare that hash value with the hash value in the database. Use a secure hash algorithm (not MD5, for example). Better yet, concatenate the username and password and hash that, then use that as the value to store in the database and compare (that way two users with the same password don't hash to the same value).
Yes. Use PreparedStatements instead. Replace the user and password values with placeholders.
String SampleQuery = "SELECT * FROM YourTable WHERE User = ? AND Password = ?";
String UserName = UsernameBox.getText();
String Password = PasswordBox.getText();
PreparedStatement prep = conn.prepareStatement(SampleQuery);
prep.setString(1, UserName);
prep.setString(2, Password);
ResultSet result = prep.executeQuery();
I inherited a project where the passwords are in plaintext in a table in the db. If I was converting to MD5 I'd just do something like
UPDATE users SET encrypted_password = MD5(password);
I'm using the java BCrypt class instead of MD5. The table has ~3 million users. Is there a optimal way to bcrypt each plaintext password into the new 'encrypted_password' column.
The only way I can think of is to loop through a ResultSet of each user, SELECT the plaintext password, bcrypt it, and then UPDATE the row. Something tells me this will take half an eternity. Anything quicker?
I think it might be the only way, and it did take forever, but I ended up just writing a simple class to iterate through each row and BCrypt the plaintext password and store it. Just for sanity, I checked if the match was good after BCrypting: I never got any mismatches. The Encryption class is just a fragment of an actual class I'm using with a lot of other encryption methods, I just included the relevant methods for clarity. If it helps anyone, here's the code:
public class Bcrypter {
public static void main(String args []) {
int lower = Integer.parseInt(args[0]);
int upper = Integer.parseInt(args[1]);
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
int row = 0;
try {
conn = Database.getConnection();
pstmt = conn.prepareStatement("SELECT id, user_pass, user_pass_bcrypt FROM users ORDER BY id LIMIT ?, ?",
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
pstmt.setInt(1, lower);
pstmt.setInt(2, upper);
rs = pstmt.executeQuery();
while (rs.next()) {
String user_pass = rs.getString("user_pass");
String user_pass_encrypted = Encryption.encrypt(user_pass);
if (Encryption.isMatch(user_pass, user_pass_encrypted)) {
rs.updateString("user_pass_bcrypt", user_pass_encrypted);
rs.updateRow();
if (++row % 10000 == 0) {
System.out.println(row);
}
} else {
System.out.println("Mismatch " + user_pass);
}
}
System.out.print("DONE");
} catch (SQLException e) {
e.printStackTrace();
System.out.print(e);
} finally {
Database.closeConnection(conn, pstmt, rs);
}
}
}
public final class Encryption {
private Encryption() {
// can't instantiate
}
/**
* Encrypts a password. The gensalt() method's default param is
* 10 but it's lowered here, assuming better performance.
*/
public static String encrypt (String plainPassword) {
return BCrypt.hashpw(plainPassword, BCrypt.gensalt(5));
}
/**
* Checks whether a plaintext password matches one that has been
* hashed previously
*/
public static Boolean isMatch(String plainPassword, String hashedPassword) {
return (BCrypt.checkpw(plainPassword, hashedPassword));
}
}
Hello I am trying to create a login form in java netbeans IDE. My aim is to create multiple user ID's and their respective passwords. I have given textfields to userID and passwordField for passwords to get the values but the problem is i want to get the text from the password field and i am unable to get it its showing some error i think there is some problem with syntax my research is as follows can there be any solution? Need your help
private void lb_loginMouseClicked(java.awt.event.MouseEvent evt) {
DBUtil util = new DBUtil();
String value1=tb_uid.getText();
String value2=tb_pwd.getPassword();
String user1="";
String pass1="";
try {
Connection con = util.getConnection();
PreparedStatement stmt = con.prepareStatement("SELECT * FROM login where username='"+value1+"' && password='"+value2+"'");
ResultSet res = stmt.executeQuery();
res = stmt.executeQuery();
while (res.next()) {
user1 = res.getString("username");
pass1 = res.getString("password");
}
if (value1.equals(user1) && value2.equals(pass1)) {
JOptionPane.showMessageDialog(this,"correct");
}
else{
JOptionPane.showMessageDialog(this,"Incorrect login or password","Error",JOptionPane.ERROR_MESSAGE);
}
JOptionPane.showMessageDialog(null, "COMMITED SUCCESSFULLY!");
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex.getMessage());
}
}
String pwd = new String(jPasswordField1.getPassword());
Option 1:
jTextField1.setText(""+pwd);
Option 2:
System.out.println(""+pwd);
Use this code:
String password = String.valueOf(jPasswordField.getPassword());
The JPasswordField is encrypted but if you use String.valueOf it will converted Char to String.
value2 is char array so doing String concatenation would result in the String representation of the array rather then the String content itself ending up in the SQL. You could replace
PreparedStatement stmt = con.prepareStatement("SELECT * FROM login where username='"+value1+"' && password='"+value2+"'");
with
PreparedStatement stmt = con.prepareStatement("SELECT * FROM login where username='"+value1+"' AND password='" + new String(value2) + "'");
Similarly
if (value1.equals(user1) && value2.equals(pass1)) {
would need to be
if (value1.equals(user1) && pass1.equals(new String(value2)) {
Better use the PreparedStatement placeholders however, to protect against SQL injection attack:
PreparedStatement stmt = con.prepareStatement("SELECT * FROM login where username=? AND password=?);
stmt.setString(1, value1);
stmt.setString(2, new String(value2));
Note: This is not a secure way do to a password lookup, a hashed comparison would be relatively safer.
From http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/String.html#equals%28java.lang.Object%29:
equals
public boolean equals(Object anObject)
Compares this string to the specified object. The result is true if
and only if the argument is not null and is a String object that
represents the same sequence of characters as this object.
Your code:
char[] value2=tb_pwd.getPassword();
...
String pass1="";
...
...&& value2.equals(pass1)...
Seems like you'd want to convert your char array into String then retry the conversion. If you're still getting an error please post it along with relevant input so we can see what is being received.
You want to convert your char[] to a String. When you envoke tb_pwd.getPassword() a char[] (character array) is returned. If you want to compare this password you must convert it to a String, and for this you can use this method:
String final_pass = "";
for(char x : passwordAsChar[]) {
final_pass += x;
}
As for comparing passwords in databases you should never store them in plain-text, unencrypted. You could store an MD5 string in your database, and the convert your password inputted by the user to a String, and then envoke the following method on it. Then compare the returned String with the one from the database. If they match, the user has entered a correct password.
Example:
char[] pass = tb_pwd.getPassword();
String final_pass = "";
for (char x : pass) {
final_pass += x;
}
String md5_encrypted_pass_userInput = encrypt(final_pass);
if (md5_encrypted_pass.equals(pass1)) { /* pass1 = the password from the database */
// Correct password
}
A method to use for encrypting Strings to MD5 is:
public static final String encrypt(String md5) {
try {
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
byte[] array = md.digest(md5.getBytes());
StringBuffer sb = new StringBuffer();
for (int i = 0; i < array.length; ++i) {
sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3));
}
return sb.toString();
} catch (java.security.NoSuchAlgorithmException e) {}
return null;
}