DB Importer

HiberObjects

Download

Order

Forum

Create DAO

The admin application we are building needs a login form. Only users with administrator privileges will be allowed to log in. If login is OK, we will display a list of existing users and a form to create new users.

We need a login function that will:

  1. Find a User by username.
  2. Check if the User is in the ADMINISTRATORS Group.
  3. Check if the password is correct. The password is encrypted in the database, so I need to handle this.

We start by creating a data access object (DAO) for users:

And then create a query for the username:

The generated query returns a list of User's, but I just want 0 or 1 User. So, I change the return type from User[*] to User:

Save the diagram and look at the generated code:

public User findByUsername(String username) { Query query = getSession().createQuery("from User u where u.username = :username"); query.setParameter("username", username); java.util.List list = query.getResultList(); if (list.size() == 1) { return (User) list.get(0); } else { return null; } }

Create a login method:

This method will find a user with the given username and check the password.

But how are the passwords encoded in phpBB3?

Password Encryption

I create a new user "testuser" with password "secret" in phpBB3. The user_password becomes "$H$7vDWP4nNLHdruWNbspt5AvSOLPmP1S/" in the database. We can use this in a unit test:

public class PHPBB3PasswordTest extends TestCase { private PHPBB3Password passwordUtil = new PHPBB3Password(); private String password = "secret"; private String encrypted = "$H$7vDWP4nNLHdruWNbspt5AvSOLPmP1S/"; public void testCheckHash() throws Exception { assertTrue(passwordUtil.phpbb_check_hash(password, encrypted)); } }

I found the PHP code that handles the encryption and ported it to Java, using the unit test to verify our results. You can see the result here.

Implementing Login

Now, we can continue on the UserDAO. We start by creating a test class:

Create 2 test methods and clean up the diagram a litte:

I will test against the MySQL database I have installed locally. I configure hibernate.properties, making sure I remove auto create-drop, so I don't accidentally clear the database:

#hibernate.hbm2ddl.auto=create-drop hibernate.dialect=org.hibernate.dialect.MySQL5Dialect hibernate.connection.driver_class=com.mysql.jdbc.Driver hibernate.connection.url=jdbc:mysql://localhost/phpbb hibernate.connection.username=<username> hibernate.connection.password=<password>

I implement the unit tests:

private UserDAO userDAO = new UserDAO(); public void testFindByUsername() throws Exception { User user = userDAO.findByUsername("testuser"); assertNotNull(user); } public void testLogin() throws Exception { User user = userDAO.login("testuser", "secret"); assertNotNull(user); } public void testLoginWrongPassword() throws Exception { User user = userDAO.login("testuser", "x"); assertNull(user); }

And then run the test:

findByUsername() works fine, now I just need to implement login:

public User login(String username, String password) { User user = findByUsername(username); if(user == null) return null; PHPBB3Password passwordUtil = new PHPBB3Password(); if(passwordUtil.phpbb_check_hash(password, user.getPassword())) return user; else return null; }

And test:

Using associations

But we only want users with administrator rights to get access to this application. In SQL, we would do something like:

select u.* from phpbb_users u, phpbb_groups g, phpbb_user_group ug where u.username = 'admin' and g.groupName = 'ADMINISTRATORS' and ug.group_id = g.group_id and ug.user_id = u.user_id

With object-relational mapping, I will find a Group object and then check if the User is in that Group.

Create one more login method in UserDAO where we also will supply groupname "ADMINISTRATORS":

Also create a query to search for Groups:

Let's test the new login method:

public void testLogin2() throws Exception { User user = userDAO.login("ADMINISTRATORS", "admin", "secret"); assertNotNull(user); } public void testLogin2NotAdmin() throws Exception { User user = userDAO.login("ADMINISTRATORS", "testuser", "secret"); assertNull(user); }

Implementing the new login method is easy:

public User login(String groupname, String username, String password) { Group group = findGroupByName(groupname); User user = login(username, password); if(user != null && group != null && user.getGroup() == group) return user; else return null; }

Group has a Set of Users, so we could do something like this if we want:

for(User u : group.getUser()) { System.out.println(u.getUsername()); }

This is a natural way to handle these objects in Java.

Next: GWT Client