Currently I am working on a program that required to add multiple user and each user will have their own password, so all the username and password will save on a same text file. My question is, is there any solution to just comparing the username and password and that it.
For example, User A login, after the user type in the Username and Password it will go through the text file and take out User A username and password without touching User B or C Username and password of user B or C
The easiest way to do this is using Properties. A Java-Properties-File look like this:
# this is a comment
name=value
user=password
I would recommend to not store the password as plain-text in your file. Saving it's hash will be enough to compare passwords:
public class YourPasswordStorage
{
Properties users = new Properties();
public YourPasswordStorage (File file)
{
user.load(file);
}
void insertUser (String user, String password)
{
users.put(user,
Base64.getEncoder().encodeToString(
MessageDigest.getInstance("sha-512").digest(password)));
}
boolean checkUser (String user, String password)
{
String hash = Base64.getEncoder().encodeToString(
MessageDigest.getInstance("sha-512").digest(password));
return (hash.equals(users.get(user)); // note that users.get(user) could be null
}
}
Note that the Code above won't compile because of some uncaught Exceptions, but I hope you understand how it works.
Storing raw passwords in a text file isn't very safe for your users. It's a lot better to salt your passwords first - systematically convert them into hash that you write to file. Then instead of comparing password to password, you take salt the password the user gives you and compare that to what's written to file. Take a look here (and many other places) for how to do that.
Have you heard NEVER GIVE A MONKEY TO DO MAN'S WORK
Well AFAICS you will have the fields username password and user so why dont use a database instead of a file.
Take advantage of H2 database allows you to store data as file.
Just include the driver jar and write this simple codes
Connection con = null;
try{
Class.forName("org.h2.Driver");
con = DriverManager.getConnection("jdbc:h2:./mydb;MODE=MySQL;", "", "");
PreparedStatement stmt= con.prepareStatement
("INSERT INTO yourTable(user,username,password) VALUES(?,?,?)");
stmt.setString(1, "someUser");
stmt.setString(2, "someUsername");
stmt.setString(3, "somePassword");
stmt.executeUpdate();
}
catch (SQLException e) {
e.printStackTrace();
}
finally{
//close statements
}
Related
I am playing around with a login/register system for a desktop application. I have a register form and sign in form and the credential information is saved to a PostgreSQL database. I started out without encrypting information and everything is working but I now want to encrypt the password to save to the database. I am using Jasypt and got the password to encrypt and save to the database:
public void actionPerformed(ActionEvent e){
if(e.getSource() == registerButton){
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.getText());
statement.setString(2, lastName.getText());
statement.setString(3, email.getText());
statement.setString(4, username.getText());
//checks password to ensure confirmation matches
//encrypts password for storing in database
if(password.getText().equals(confPass.getText())){
StrongPasswordEncryptor passwordEncryptor = new StrongPasswordEncryptor();
String encryptPass = passwordEncryptor.encryptPassword(password.toString());
statement.setString(5, encryptPass);
statement.executeUpdate();
JOptionPane.showMessageDialog(null, "Registered Successfully");
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
}
else{
JOptionPane.showMessageDialog(null, "Password did not match");
}
} catch(SQLException f){
f.printStackTrace();
}
}
This works well and my password is encrypted. I am stumped on where to begin with getting the password from the database to compare the encrypted password to the user input. My sign in form to compare passwords (prior to encrypting the password):
public void actionPerformed(ActionEvent e){
//verify users credentials and signs in
if(e.getSource() == login){
try{
//connects to the database
Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/cc","pi","server");
//inserts values into table
PreparedStatement statement = conn.prepareStatement("SELECT username, user_pass FROM users WHERE username = ? and user_pass = ?");
statement.setString(1, username.getText());
statement.setString(2, password.getText());
ResultSet result = statement.executeQuery();
if (result.next()) {
frame.dispose();
new CommunityCooks();
}
else {
JOptionPane.showMessageDialog(null, "Username or Password did not match.");
}
}
catch(SQLException f){
f.printStackTrace();
}
}
I made a test app to compare encrypted passwords and have a general idea of how it works:
import org.jasypt.util.password.StrongPasswordEncryptor;
public class EncryptTest {
public static void main(String[] args) {
String userPass = "test";
StrongPasswordEncryptor passwordEncryptor = new StrongPasswordEncryptor();
String encryptPass = passwordEncryptor.encryptPassword(userPass);
System.out.println(encryptPass);
if(passwordEncryptor.checkPassword("test", encryptPass)){
System.out.println("correct");
}
else{
System.out.println("wrong");
}
}
}
The part that I am stumped on is trying to get the encrypted password and compare it to the user input password to validate. I believe I need to encrypt the input password and then can use the passworEncryptor.checkPassword(); but I don't know exactly where to put that in the sign in code and how to implement it. Any help would be great.
Thank you.
The name of the Java library Jasypt is shortened for "Java Simplified Encryption" and so this library is trying to avoid that
users are making implementations of crypto-routines that become insecure because of implementation errors.
The validation of a user password is as simple as your test app - you do not need to implement an encryption part, just pass the
password the user typed in your login form and pass it to the validation part
In details: There are two parts - in part 1 the user registers with his userPassword and passes it to the encryptPassword method:
String userPassword = "myPassword";
String encryptedPassword = passwordEncryptor.encryptPassword(userPassword);
encryptedPassword example: rCAgedhPnGoDZ1PF7hgspDIhLnLAHo536PSCKUfpYu8Yv0JHEcIZ3ZVHIHojBn1D
This encrypted password get stored in the database and you have to keep in mind that you cannot restore the original password from this string!
In part 2 the user tries to login with his loginPassword and passes it to the checkPassword method. The program loads the encryptedPassword from the database and passes the loginPassword together with the encryptedPassword. The result (boolean) is checked and the next steps in your program depend on the result, "true" means that the loginPassword is correct and "false" means that the loginPassword is not correct.
String loginPassword = "myPassword";
if (passwordEncryptor.checkPassword(loginPassword, encryptedPassword)) {
// correct!
System.out.println("correct passsword");
} else {
// bad login!
System.out.println("password not correct");
}
For more information you can check the "Easy usage" webpage: http://www.jasypt.org/easy-usage.html
I'm creating very simple ATM machine. I have MySQL DB with columns like: loginID, password, money. I would like to change my method which can verify correctness of login and password at the beginning (and after this do something). So If login and password are correct, then I want to receive a message "Login successful" or Login unsuccessful". Right now I always have message "Login successful". How can I change it?
public static void post () throws Exception{
Scanner sc = new Scanner(System.in);
System.out.println ("please enter user id:");
String userId = sc.nextLine();
System.out.println("please enter password:");
String pass = sc.nextLine();
System.out.println("how much you want to put");
int money = sc.nextInt();
try {
Connection con = ConnectionDB.getConnection();
String sql = "UPDATE `BankDB`.`Info` SET `Money`= ? WHERE `ClientID`= ? AND `ClientPass` = ?";
PreparedStatement posted = con.prepareStatement(sql);
posted.setInt(1, money);
posted.setString(2, userId);
posted.setString(3, pass);
posted.executeUpdate();
con.close();
} catch (Exception e) {
e.printStackTrace();
} finally{
System.out.println("Login was succesful");
}
}
If my understanding of the question is valid, you need to check that update command really updated something in DB.
In this case you need to get result from posted.executeUpdate(). If it is greater than zero, update updated record in DB and user name / password were correct.
UPDATE queries work even if their WHERE clauses choose zero rows. So your query
UPDATE `BankDB`.`Info` SET `Money`= ? WHERE `ClientID`= ? AND `ClientPass` = ?
doesn't do anything if either part of the WHERE clause matches nothing. But it still succeeds.
Generally you want to do something like shown in this outline.
SELECT id, password FROM Info WHERE ClientId = ?
Check the password for a match with the one provided by your web user. If it doesn't match, reject the transaction.
UPDATE Info SET Money = Money + ? WHERE id = ? giving the id value you retrieved in the first step.
DANGER your way of validating the user's password is incredibly dangerous in a world infested with cybercriminals. Storing plain-text passwords in a dbms is notorious for being the worst thing you can do about security. This is about password hashing in php, but its advice is valid for any language. Please read it. http://php.net/manual/en/faq.passwords.php Don't reinvent the flat tire in the area of password security. Please.
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 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.
I have made some code in ECLIPSE. As you can see, the username, password, database URL, SQL Queries are hardcoded into my program. I don't want to change my code and recompile it every time I change the password, username of my database or modify the query. For that reason, I want to put these "parameters" inside a file (text, XML, json ???). I want to be able to change the parameters easily.
So what should I do ? What kind of file should I use ? I want to avoid XML, json because
you need to know both well. XML and JSON can be difficult when the code grows big.
import java.sql.*;
public class JDBCDemo {
static String query =
"SELECT customerno, name " +
"FROM customers;";
public static void main(String[]args)
{
String username = "cowboy";
String password = "123456";
try
{
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/business", username, password);
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
}catch(SQLException ex){System.out.println("Exception! " + ex);}
}
}
You can use
Properties
and read the values from a .properties file.
Maybe this helps. It's an example of such config files.
InputStream inputStream = null;
Properties properties = new Properties();
try {
inputStream = JDBCDemo.class.getClassLoader().getResourceAsStream("jdbc.properties");
properties.load(inputStream);
}
finally {
try {
if (inputStream != null) {
inputStream.close();
}
}
catch (IOException e) {
;//ignore
}
}
String username = properties.get("username");
XML and JSON are structured formats so they needs to be parsed.
Text file will be the simplest to implement but because it is unstructured the end user is going to need going to need to know the internal format understood by your program. For instance an extra space may break your program.
Ever think of using spring injection where u can create one config file containing all hardcoded variables which through getters and setters can be put into your code. Then in the future if any of these variables need changing you only change 1 file
http://www.springsource.org/javaconfig/
generally the uer-id & passwords (rather any resource that needs to be configured from outside your JAR/WAR) is stored in a Properties file as a key value pair. You can then access them using ResourceBundle class : http://docs.oracle.com/javase/1.4.2/docs/api/java/util/ResourceBundle.html
For sql queries you could use a database function or procedure which returns some kind of cursor similar to SYS_REFCURSOR in Oracle and call the function or procedure from front end. By doing this you could avoid hard coding of sql queries in java code.
Regards