Authentication using database

1) Defining the Domain

(model.groovy)

Entity ('User') {

      string_32  'login', mandatory:true, unicityScope:'scope_login'

      password 'password'     

      enumeration 'language', enumName:'language', values:['fr', 'en']

      set 'roles', ref:'Role', reverse:'Role-users'

 

Entity ('Role') {

      string_32 'roleId'

      set 'users', ref:'User', composition:false, reverse:'User-roles'

}

2) Update Jaas.config to use the new org.jspresso.framework.security.auth.spi.DatabaseLoginModule (3.5 +). This login module extends the Jboss security DatabaseServerLoginModule, so configuration apply.
(take care to setup java.security.auth.login.config parameter into your tomcat launcher as described in the startup tutorial)

myproject {

   org.jspresso.framework.security.auth.spi.DatabaseLoginModule required

       dsJndiName="java:comp/env/jdbc/MyProjectDS"

       principalsQuery="SELECT PASSWORD, LANGUAGE language FROM USER WHERE LOGIN=?"

       rolesQuery="SELECT ROLE.ROLE_ID, 'Roles' FROM ROLE, USER, USER_ROLES \

                   WHERE USER.LOGIN=? AND USER_ROLES.ROLE_ID=ROLE.ID AND USER_ROLES.USER_ID=USER.ID"

       principalClass=org.jspresso.framework.security.UserPrincipal

       suspendResume=false;  

};

3) For TOMCAT :

Define a jndi name for your database context.xml into tomcat conf directory

<Context>

    <Resource name="jdbc/MyProjectDS" auth="Container" type="javax.sql.DataSource"

           maxActive="100" maxIdle="30" maxWait="10000"

           username="root" password="pwd" driverClassName="com.mysql.jdbc.Driver"

           url="jdbc:mysql://10.61.168.88:3306/myproject"/>
</
Context>

NB : Take care that tomcat lib contains the jdbc lib library (for example mysql-connector-java-x.x.x.jar )

Setup your datasource project : use the jndi name above
(myproject/webapp/src/main/dev/resources/fr/gefco/myproject/config.xml)

<beans

  xmlns="http://www.springframework.org/schema/beans"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xsi:schemaLocation="http://www.springframework.org/schema/beans

                      http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"

  default-lazy-init="true">

 

  <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">

   <property name="jndiName" value="java:comp/env/jdbc/MyProjectDS"/>

 </bean>


</beans>

4) For SWING:

4.a) Define the datasource directly into /myproject/core/src/main/resources/fr/gefco/weather/config.xml

  <bean

    id="dataSource"

    class="org.apache.commons.dbcp.BasicDataSource">

    <property

      name="driverClassName"

      value="com.mysql.jdbc.Driver" />

    <property

      name="url"

      value="jdbc:mysql://localhost:3306/myproject" />

    <property

      name="username"

      value="root" />

    <property

      name="password"

      value="pwd" />

  </bean>

 

4.b) Update your SwingApplicationStartup class to setup the jndi name for your database :

  @Override

  public void start() {

    DataSource dataSource = (DataSource) getApplicationContext().getBean("dataSource", DataSource.class);

    try {

      InitialContext ic = new InitialContext();

      Context compSubContext = ic.createSubcontext("java:comp");

      Context envSubContext = compSubContext.createSubcontext("env");

      Context jdbcSubContext = envSubContext.createSubcontext("jdbc");

      jdbcSubContext.rebind("MyProjectDS", dataSource);

    } catch (NamingException ex) {

      throw new NestedRuntimeException(ex);

    }

    super.start();

  }

 

4.c) Add a JNDI library to your Jspresso application Launcher.

For my own i'm using Simple-JNDI : you have to add following VM arguments :

-Djava.naming.factory.initial=org.osjava.sj.SimpleContextFactory
-Dorg.osjava.sj.delimiter=/
-Dorg.osjava.sj.jndi.shared=true
-Dorg.osjava.sj.root=conf


5) This step is optional. The Jspresso database login module will store all extra column you put into the principals query (e.g. language in our case) into the session user principal custom properties. However, you might want to keep the user entity instance itself into the application session (also as a custom property). Here is how you would do it using a simple startup action.

a. Add a startup application
(frontend.groovy)

     controller (myproject.name', startup:'startupBackAction')

(backend.groovy)

action ('startupBackAction',    class:'org.mycompany.myproject.backend.StartupBackAction')

b.  Code your startup action

 

public class StartupBackAction extends AbstractHibernateAction {

 

  public final static String USER_ENTITY_KEY = "session.userEntity";

 

  @SuppressWarnings("unchecked")

  @Override

  public boolean execute(IActionHandler actionHandler, final Map<String, Object> context) {

    final UserPrincipal userPrincipal = getBackendController(context).getApplicationSession().getPrincipal();

 

    User user = (User)getTransactionTemplate(context).execute(new TransactionCallback() {

     

      public Object doInTransaction(TransactionStatus txStatus) {

        User user = null;

       

        DetachedCriteria userCriteria = DetachedCriteria.forClass(User.class);

        userCriteria.add(Restrictions.eq("login", userPrincipal.getName()));

           

        List<User> users = getHibernateTemplate(context).findByCriteria(userCriteria);

        if (users!=null && !users.isEmpty()) {

          user = users.get(0);

        }

       

        txStatus.setRollbackOnly();

        return user;

      }

    });

   

    // merge hibernate instance into session 

    user = (User)getController(context).merge(user, EMergeMode.MERGE_KEEP);

   

    // set custom property

    userPrincipal.putCustomProperty(USER_ENTITY_KEY, user);

    return super.execute(actionHandler, context);

  }

 

}

6) Code an administration workspace for User and Role entity
That will not take a while using Jspresso ;)

 

You should be done !