4 Replies Latest reply on Apr 1, 2004 11:47 PM by sanjuthomas

    CustomLoginModule implementation

    sanjuthomas

      we are trying to migrate from Weblogic to JBoss, now we need to implement securty policy for our EJBs, we have written cusotm class for the security implementation extending UsernamePasswordLoginModule. Then we created jar using this class and put in the jboss_home/server/default/lib direcoty , and we have made right changes in login-config.xml and EJB's jboss.xml (hopefully)

      login-config.xml

      <application-policy name="OptiwiseSecurityDomain">

      <login-module code="com.optiwise.bl.core.security.OptiwiseServerLoginModule" flag="required"></login-module>

      </application-policy>

      jboss.xml

      <?xml version="1.0"?>

      <security-domain>java:/jaas/OptiwiseSecurityDomain</security-domain>


      When running jboss server i have got log like this

      09:48:54,606 INFO [MainDeployer] Starting deployment of package: file:/C:/jboss
      -3.2.2/jboss-3.2.2/server/default/deploy/RequestMgr.jar
      09:48:54,936 INFO [EjbModule] Deploying RequestMgr
      09:48:54,946 INFO [JaasSecurityManagerService] Created securityMgr=org.jboss.se
      curity.plugins.JaasSecurityManager@a59490
      09:48:54,956 INFO [JaasSecurityManagerService] setCachePolicy, c=org.jboss.util
      .TimedCachePolicy@945b95
      09:48:54,966 INFO [JaasSecurityManagerService] Added OptiwiseSecurityDomain, or
      g.jboss.security.plugins.SecurityDomainContext@8a6fc to map
      09:48:55,017 INFO [StatelessSessionInstancePool] Started jboss.j2ee:jndiName=Re
      questMgr,plugin=pool,service=EJB
      09:48:55,017 INFO [StatelessSessionContainer] Started jboss.j2ee:jndiName=Reque
      stMgr,service=EJB
      09:48:55,027 INFO [EjbModule] Started jboss.j2ee:module=RequestMgr.jar,service=
      EjbModule
      09:48:55,027 INFO [EJBDeployer] Deployed: file:/C:/jboss-3.2.2/jboss-3.2.2/serv
      er/default/deploy/RequestMgr.jar
      09:48:55,037 INFO [MainDeployer] Deployed package: file:/C:/jboss-3.2.2/jboss-3
      .2.2/server/default/deploy/RequestMgr.jar


      so i think in the server side everything is fine, if it is not please tell me

      client program

      import javax.naming.InitialContext;
      import javax.security.auth.login.LoginContext;

      import org.apache.log4j.Logger;
      import org.jboss.security.auth.callback.UsernamePasswordHandler;

      /**
      * @author Optiwise
      */
      public class OptiwiseClient
      {
      public static void main(String args[]) throws Exception
      {
      Logger log = Logger.getLogger("RequestMgr");
      log.info("Login with username="+args[0]+", password="+args[1]);
      UsernamePasswordHandler handler = new UsernamePasswordHandler(args[0], args[1].toCharArray());
      LoginContext lc = new LoginContext("RequestMgr", handler);
      lc.login();
      log.info("Looking up RequestMgr Bean");
      InitialContext iniCtx = new InitialContext();
      Object ref = iniCtx.lookup("RequestMgr");
      RequestMgrHome home = (RequestMgrHome) ref;
      RequestMgr ob1 = home.create();
      log.info("Created Request Manager Object");
      log.info(ob1);
      System.out.println(ob1);
      lc.logout();
      }
      }

      but when i am running client program i am getting an exception that is copied here

      F:\sanju\work\JBoss>java OptiwiseClient sanju sanju
      Exception in thread "main" java.lang.SecurityException: Unable to locate a login
      configuration
      at com.sun.security.auth.login.ConfigFile.(ConfigFile.java:97)
      at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

      at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstruct
      orAccessorImpl.java:39)
      at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingC
      onstructorAccessorImpl.java:27)
      at java.lang.reflect.Constructor.newInstance(Constructor.java:274)
      at java.lang.Class.newInstance0(Class.java:296)
      at java.lang.Class.newInstance(Class.java:249)
      at javax.security.auth.login.Configuration$3.run(Configuration.java:221)

      at java.security.AccessController.doPrivileged(Native Method)
      at javax.security.auth.login.Configuration.getConfiguration(Configuratio
      n.java:215)
      at javax.security.auth.login.LoginContext$1.run(LoginContext.java:170)
      at java.security.AccessController.doPrivileged(Native Method)
      at javax.security.auth.login.LoginContext.init(LoginContext.java:167)
      at javax.security.auth.login.LoginContext.(LoginContext.java:393)
      at OptiwiseClient.main(OptiwiseClient.java:21)
      Caused by: java.io.IOException: Unable to locate a login configuration
      at com.sun.security.auth.login.ConfigFile.init(ConfigFile.java:206)
      at com.sun.security.auth.login.ConfigFile.(ConfigFile.java:95)
      ... 14 more


      if somebody knows the real problem , please help us, we are looking for you help.
      we need to implement in short time, please give ur advice. if there is anyother files
      to make changes please tell me that too, i am not quit sure that i am running on the
      right path , please help me.

      if anyone need our custom security class we will provide, so that you can fine
      any error on that , if it is there.

      thanking you
      sanju

        • 1. Re: CustomLoginModule implementation
          mckenzis

          I believe that when you instantiate the LoginContext you must make reference to the domain you want a context with.

          change LoginContext lc = new LoginContext("RequestMgr", handler);
          to LoginContext lc = new LoginContext("OptiwiseSecurityDomain", handler);

          • 2. Re: CustomLoginModule implementation
            sanjuthomas

            thank you for your help, i made changes , & i got the result too, now the sever is looking for security class, but the problem is the custom class is unable to find the datasource, it is telling that OracleDS not bound, on the same time other EJBs are able to access the DataSource, please help me, if you need the Custom Security class code i will send you, we are looking for you
            thanking you
            sanju

            • 3. Re: CustomLoginModule implementation
              sanjuthomas

              thank you for your help, actually that was the problem, it is working now, but now this custom class is unable to access datasource on the same time other beans are accessing the datasource, any idea, i will give you the custom class code now.

              the code in given below, i made some changes in one example code,so you please see this.

              /*
              * Optiwise Custom Security Class
              * A JDBC based login module that supports authentication and role mapping.
              */



              package com.optiwise.bl.core.security;

              import java.security.acl.Group;
              import java.util.HashMap;
              import java.util.Map;
              import java.sql.Connection;
              import java.sql.PreparedStatement;
              import java.sql.ResultSet;
              import java.sql.SQLException;
              import javax.naming.InitialContext;
              import javax.naming.NamingException;
              import javax.sql.DataSource;
              import javax.security.auth.Subject;
              import javax.security.auth.callback.CallbackHandler;
              import javax.security.auth.login.LoginException;
              import javax.security.auth.login.FailedLoginException;
              import org.jboss.security.SimpleGroup;
              import org.jboss.security.SimplePrincipal;
              import org.jboss.security.auth.spi.UsernamePasswordLoginModule;

              public class OptiwiseServerLoginModule extends UsernamePasswordLoginModule
              {
              private String dsJndiName = "java:/OracleDS";
              private String principalsQuery = "SELECT OW_PASSWORD FROM OW_T_USER WHERE OW_USERID=?";
              private String rolesQuery = "SELECT OW_T_ROLE.OW_NAME FROM OW_T_ROLE WHERE OW_OID IN (SELECT OW_T_USERROLE.OW_ROLEOID FROM OW_T_USERROLE WHERE OW_USEROID = (SELECT OW_T_USER.OW_OID FROM OW_T_USER WHERE OW_USERID=?))";
              /**
              * Initialize this LoginModule.
              */
              public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options)
              {
              super.initialize(subject, callbackHandler, sharedState, options);

              log.trace("DatabaseServerLoginModule, dsJndiName="+dsJndiName);
              log.trace("principalsQuery="+principalsQuery);
              log.trace("rolesQuery="+rolesQuery);
              }

              /** Get the expected password for the current username available via
              * the getUsername() method. This is called from within the login()
              * method after the CallbackHandler has returned the username and
              * candidate password.
              * @return the valid password String
              */

              protected String getUsersPassword() throws LoginException,java.rmi.RemoteException
              {
              String username = getUsername();
              String password = null;
              Connection conn = null;
              PreparedStatement ps = null;
              try
              {
              InitialContext ctx = new InitialContext();
              DataSource ds = (DataSource) ctx.lookup(dsJndiName);
              conn = ds.getConnection();
              // Get the password
              ps = conn.prepareStatement(principalsQuery);
              ps.setString(1, username);
              ResultSet rs = ps.executeQuery();
              if( rs.next() == false )
              throw new FailedLoginException("No matching username found in Principals");
              password = rs.getString(1);
              password = convertRawPassword(password);
              rs.close();
              }
              catch(NamingException ex)
              {
              log.error("Problem in accessing DataSource");
              throw new LoginException(ex.toString(true));
              }
              catch(SQLException ex)
              {
              log.error("Query failed", ex);
              throw new LoginException(ex.toString());
              }
              finally
              {
              if( ps != null )
              {
              try
              {
              ps.close();
              }
              catch(SQLException e)
              {
              e.printStackTrace();
              }
              }
              if( conn != null )
              {
              try
              {
              conn.close();
              }
              catch (SQLException ex)
              {
              ex.printStackTrace();
              }
              }
              }
              return password;
              }

              /** Overriden by subclasses to return the Groups that correspond to the
              to the role sets assigned to the user. Subclasses should create at
              least a Group named "Roles" that contains the roles assigned to the user.
              A second common group is "CallerPrincipal" that provides the application
              identity of the user rather than the security domain identity.
              @return Group[] containing the sets of roles
              */

              protected Group[] getRoleSets() throws LoginException
              {
              String username = getUsername();
              Connection conn = null;
              HashMap setsMap = new HashMap();
              PreparedStatement ps = null;
              try
              {
              InitialContext ctx = new InitialContext();
              DataSource ds = (DataSource) ctx.lookup(dsJndiName);
              conn = ds.getConnection();
              // Get the users role names
              ps = conn.prepareStatement(rolesQuery);
              ps.setString(1, username);
              ResultSet rs = ps.executeQuery();
              if( rs.next() == false )
              {
              if( getUnauthenticatedIdentity() == null )
              throw new FailedLoginException("No matching username found in Roles");
              /* We are running with an unauthenticatedIdentity so create an empty Roles set and return.*/
              Group[] roleSets = { new SimpleGroup("Roles") };
              return roleSets;
              }
              do
              {
              String name = rs.getString(1);
              String groupName = rs.getString(2);
              if( groupName == null || groupName.length() == 0 )
              groupName = "Roles";
              Group group = (Group) setsMap.get(groupName);
              if( group == null )
              {
              group = new SimpleGroup(groupName);
              setsMap.put(groupName, group);
              }
              group.addMember(new SimplePrincipal(name));
              }
              while( rs.next() );
              rs.close();
              }
              catch(NamingException ex)
              {
              throw new LoginException(ex.toString(true));
              }
              catch(SQLException ex)
              {
              super.log.error("SQL failure", ex);
              throw new LoginException(ex.toString());
              }
              finally
              {
              if( ps != null )
              {
              try
              {
              ps.close();
              }
              catch(SQLException e)
              {
              e.printStackTrace();
              }
              }
              if( conn != null )
              {
              try
              {
              conn.close();
              }
              catch (Exception ex)
              {}
              }
              }
              Group[] roleSets = new Group[setsMap.size()];
              setsMap.values().toArray(roleSets);
              return roleSets;
              }
              /** A hook to allow subclasses to convert a password from the database
              into a plain text string or whatever form is used for matching against
              the user input. It is called from within the getUsersPassword() method.
              @param rawPassword, the password as obtained from the database
              @return the argument rawPassword
              */
              protected String convertRawPassword(String rawPassword)
              {
              return rawPassword;
              }
              }



              • 4. Re: CustomLoginModule implementation
                sanjuthomas

                When running the client , we are getting this exception, if anybody have got idea , please tell us.

                F:\sanju\work\JBoss>java -Djava.security.auth.login.config=F:\sanju\work\JBoss\a
                uth.conf OptiwiseClient sanju sanju
                Exception in thread "main" javax.security.auth.login.LoginException: javax.namin
                g.NameNotFoundException: OracleDS not bound
                at com.optiwise.bl.core.security.OptiwiseServerLoginModule.getUsersPassw
                ord(OptiwiseServerLoginModule.java:137)
                at org.jboss.security.auth.spi.UsernamePasswordLoginModule.login(Usernam
                ePasswordLoginModule.java:150)
                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
                java:39)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
                sorImpl.java:25)
                at java.lang.reflect.Method.invoke(Method.java:324)
                at javax.security.auth.login.LoginContext.invoke(LoginContext.java:664)
                at javax.security.auth.login.LoginContext.access$000(LoginContext.java:1
                29)
                at javax.security.auth.login.LoginContext$4.run(LoginContext.java:599)
                at java.security.AccessController.doPrivileged(Native Method)
                at javax.security.auth.login.LoginContext.invokeModule(LoginContext.java
                :596)
                at javax.security.auth.login.LoginContext.login(LoginContext.java:523)
                at OptiwiseClient.main(OptiwiseClient.java:24)