CodenameOne – User authentication & password hashing with jBCrypt API
In this tutorial we’ll implement the user registration and login . We’ll use the jBCrypt API for password hashing .
Preparing the project
To test out the user registration and login we’ll need a User entity, a user DAO class ( just to follow up with the work we did in previous tutorials) a login form and the after-login home form as follows :
Also you need to download the jBycrypt 0.4 jar and add it to your project .
MyApplication.java:
public class MyApplication { private Form current; private Resources theme; public void init(Object context) { theme = UIManager.initFirstTheme("/theme"); Toolbar.setGlobalToolbar(true); } public void start() { if (current != null) { current.show(); return; } Form hi = new Form("Auth test", new BoxLayout(BoxLayout.Y_AXIS)); TextField tfUsrname = new TextField(); tfUsrname.setHint("username"); TextField tfEmail = new TextField(); tfEmail.setHint("email"); TextField tfPassword = new TextField(); TextField tfConfirmPswd = new TextField(); tfPassword.setHint("password"); Button registerBtn = new Button("Register"); registerBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { // ... }); Label toLoginLbl = new Label("Already a member?"); toLoginLbl.getUnselectedStyle().setAlignment(Component.CENTER); Font fnt = Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_ITALIC, Font.SIZE_MEDIUM); toLoginLbl.getUnselectedStyle().setFont(fnt); toLoginLbl.addPointerReleasedListener(new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { new Login().show(); } }); hi.add(tfUsrname); hi.add(tfEmail); hi.add(tfPassword); hi.add(tfConfirmPswd); hi.add(registerBtn); hi.add(toLoginLbl); hi.show(); } public void stop() { current = Display.getInstance().getCurrent(); if (current instanceof Dialog) { ((Dialog) current).dispose(); current = Display.getInstance().getCurrent(); } } public void destroy() { } }
Login.java:
public class Login extends Form { public Login() { TextField tfUsrnm = new TextField(); tfUsrnm.setHint("username"); TextField tfPassword = new TextField(); tfPassword.setHint("password"); Button lgnBtn = new Button("Login"); lgnBtn.addActionListener((ActionListener) (ActionEvent evt) -> { // ... }); setLayout(new BoxLayout(BoxLayout.Y_AXIS)); setTitle("Auth test"); add(tfUsrnm); add(tfPassword); add(lgnBtn); setBackCommand(new Command("Back") { @Override public void actionPerformed(ActionEvent evt) { showBack(); } }); } }
Registration and password hashing
To register a new user we need to perform some simple data validation tests, such as checking the content of our textfields fits a certain criterias, or checking if email and username tapped already exist in the database or not . If not, we’ll communicate it to the user through dialog messages. If data is validated we’ll simply create a hashed password with BCrypt.hashpw method, add the 2y id and insert a new user to DB with this value for the password field.
registerBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { ConnectionRequest con = new ConnectionRequest(); ConnectionRequest con2 = new ConnectionRequest(); con.setUrl("http://localhost/testLogin/findUser.php?username=" + tfUsrname.getText()); con2.setUrl("http://localhost/testLogin/findMail.php?email=" + tfEmail.getText()); con.addResponseListener((NetworkEvent evt1) -> { con2.addResponseListener(new ActionListener() { public void actionPerformed(NetworkEvent evt2) { UserDAO userDAO = new UserDAO(); userDAO.getUsersList(new String(con.getResponseData())); //regestration conditions if ((tfUsrname.getText().equals("")) || (tfEmail.getText().equals("")) || (tfPassword.getText().equals("")) || (tfConfirmPswd.getText().equals(""))) { Dialog.show("Erreur", "Please fill all fields", "Ok", null); } if (!(tfPassword.getText().length() > 7)) { Dialog.show("Erreur", "Password should contain at least 8 characters", "Ok", "Cancel"); tfPassword.setText(""); } else { if ((userDAO.getUsersList(new String(con2.getResponseData())).size() == 0) && (userDAO.getUsersList(new String(con.getResponseData())).size()) == 0 && (tfPassword.getText().equals(tfConfirmPswd.getText())) && (tfPassword.getText().length() > 7) && (tfEmail.getText().endsWith("@esprit.tn") || tfEmail.getText().endsWith("@gmail.com") || tfEmail.getText().endsWith("@hotmail.com") || tfEmail.getText().endsWith("@yahoo.com") || tfEmail.getText().endsWith("@yahoo.fr") || tfEmail.getText().endsWith("@hotmail.fr")) && (!tfUsrname.getText().equals("")) && (!tfEmail.getText().equals(""))) { String originalPassword = tfPassword.getText(); String generatedSecuredPasswordHash = BCrypt.hashpw(originalPassword, BCrypt.gensalt(13)); String souchaine = generatedSecuredPasswordHash.substring(4, generatedSecuredPasswordHash.length()); String pwd = "$2y$" + souchaine; System.out.println(pwd); userDAO.registration(tfUsrname.getText(), tfEmail.getText(), generatedSecuredPasswordHash); new Login().show(); } // if ((userDAO.getUsersList(new String(con2.getResponseData())).size() > 0)) { Dialog.show("Erreur", "Mail already exists", "Ok", null); tfEmail.setText(""); } /*if ((userDAO.getUsersList(new String(con.getResponseData())).size() > 0)) { Dialog.show("Erreur", "Username already in use", "Ok", null); tfUsrname.setText(""); }*/ if (!(tfPassword.getText().equals(tfConfirmPswd.getText()))) { Dialog.show("Erreur", "Passwords not matching", "Ok", null); tfPassword.setText(""); tfConfirmPswd.setText(""); } if (!(tfEmail.getText().endsWith("@esprit.tn") || tfEmail.getText().endsWith("@gtfEmail.com") || tfEmail.getText().endsWith("@hottfEmail.com") || tfEmail.getText().endsWith("@yahoo.com") || tfEmail.getText().endsWith("@yahoo.fr") || tfEmail.getText().endsWith("@hottfEmail.fr"))) { Dialog.show("Erreur", "Please correct email address", "Ok", null); tfEmail.setText(""); } } } }); }); NetworkManager.getInstance().addToQueue(con); NetworkManager.getInstance().addToQueue(con2); } });
Login
For user authentication we’ll use the BCrypt.checkpw() method to check if the password of the user corresponding to username tapped, matched the one tapped in the password textfield:
lgnBtn.addActionListener((ActionListener) (ActionEvent evt) -> { ConnectionRequest con = new ConnectionRequest(); con.setUrl("http://localhost/testLogin/findUser.php?username=" + tfUsrnm.getText()); con.addResponseListener((NetworkEvent evt1) -> { UserDAO userDAO = new UserDAO(); userDAO.getUsersList(new String(con.getResponseData())); if ((userDAO.getUsersList(new String(con.getResponseData())).size()) > 0) { //Transformer le cryptage de 2y a 2a String souchaine = userDAO.getUsersList(new String(con.getResponseData())).get(0).getPassword().substring(4, userDAO.getUsersList(new String(con.getResponseData())).get(0).getPassword().length()); String javapwd = "$2a$" + souchaine; if (tfUsrnm.getText().equals(userDAO.getUsersList(new String(con.getResponseData())).get(0).getUsername()) && BCrypt.checkpw(tfPassword.getText(), javapwd)) { System.out.println("Succes"); //variable.idUser = utilisateurDAO.getUsersList(new String(con.getResponseData())).get(0).getId(); Dialog.show("Connécté", "Connécté en tant que" + tfUsrnm.getText(), "Ok", "Cancel"); new HomePage().show(); } else { Dialog.show("Authentification échoué", "Login ou mot de passe incorrect", "Ok", "Cancel"); } } else { Dialog.show("Authentification échoué", "Login ou mot de passe incorrect", "Ok", "Cancel"); } }); NetworkManager.getInstance().addToQueue(con); });
That’s all for this tutorial folks ! We’ll meet in another codename one tutorial !
Recent Comments