Show TOC Start of Content Area

This graphic is explained in the accompanying text Example Login Module  Locate the document in its SAP Library structure

This login module gets one part of the user ID that is sent with an HTTP request, and compares its first part with a given string that is specified as an option of the login module.

You can use the AbstractLoginModule class to make a login module. The AbstractLoginModule is common for all the UMSPI login modules and is an implementation of the JAAS LoginModule interface. The class is located in the com.sap.engine.interfaces.security.auth package.

For example, if you specify Admin as value of the user_name_prefix option using the Visual Administrator tool, all user with names starting with Admin and existing in the currently active user store (in this tutorial that is the UME User Store) will pass the authentication process successfully.

For more information about how to create and configure a new login module, see Create and Configure a Login Module.

/*

 * Define the extended class

 */

public class ExampleLoginModule extends AbstractLoginModule {

 

   // Define the variables that will be used later on:

   private CallbackHandler callbackHandler = null;

   private Subject subject = null;

   private Map sharedState = null;

   private Map options = null;

 

   // This is the name of the user you have created on

   // the J2EE Engine so you can test the login module

   private String userName = null;

   private boolean successful;

   private boolean nameSet;

 

   /**

    * The method initializes the login module with the

    * relevant authentication and state information.

    */

   public void initialize(

      Subject subject,

      CallbackHandler callbackHandler,

      Map sharedState,

      Map options) {

 

      // This is the only required step for the method

      super.initialize(subject, callbackHandler, sharedState, options);

 

      // Initializing the values of the variables

      this.callbackHandler = callbackHandler;

      this.subject = subject;

      this.sharedState = sharedState;

      this.options = options;

      this.successful = false;

      this.nameSet = false;

   }

 

   /**

    * Retrieves the user credentials and checks them. This is

    * the first part of the authentication process.

    */

   public boolean login() throws LoginException {

 

      // Retrieve the user credentials via the callback

      // handler.

      // In this case we get the user name from the HTTP

      // request parameters.

 

      Callback[] callbacks = new Callback[1];

 

      callbacks[0] = new HttpGetterCallback();

 

      /* The type and the name specify which part of the HTTP request

       * should be retrieved. For Web container authentication, the

       * supported types are defined in the interface

       * com.sap.engine.lib.security.http.HttpCallback.

       * For programmatical authentication with custom callback

       * handler the supported types depend on the used callback handler.

       */

      ((HttpGetterCallback) callbacks[0]).setType(

         HttpCallback.REQUEST_PARAMETER);

      ((HttpGetterCallback) callbacks[0]).setName("user_name");

 

      try {

         callbackHandler.handle(callbacks);

      } catch (UnsupportedCallbackException e) {

         return false;

      } catch (IOException e) {

         throwUserLoginException(e, LoginExceptionDetails.IO_EXCEPTION);

      }

 

      //Returns an array of all request parameters with name "user_name".

      String[] requestParameters =

         (String[]) ((HttpGetterCallback) callbacks[0]).getValue();

      if ((requestParameters != null) && requestParameters.length > 0) {

         userName = requestParameters[0];

      }

      if (userName == null) {

         throwNewLoginException("No user name provided.");

      }

 

      /* When you know the user name, update the user information

       * using data from the persistence. The operation must

       * be done before the user credentials checks. This method also

       * checks the user name so that if a user with that name does not

       * exist in the active user store, a

       * java.lang.SecurityException is thrown.

       */

 

      try {

         refreshUserInfo(userName);

      } catch (SecurityException e) {

         throwUserLoginException(e);

      }

 

      /* Checks if the given user name starts with the specified

       * prefix in the login module options. If no prefix is specified,

       * then all users are trusted.

       */

      String prefix = (String) options.get("user_name_prefix");

      if ((prefix != null) && !userName.startsWith(prefix)) {

         throwNewLoginException("The user is not trusted.");

      }

 

      /* This is done if the authentication of the login module is     

       * successful.

       * Only one and exactly one login module from the stack must put

       * the user name in the shared state. This user name represents

       * the authenticated user.

       * For example if the login attempt is successful, method

       * getRemoteUser() of

       * the HTTP request will retrieve exactly this name.

       */

 

      if (sharedState.get(AbstractLoginModule.NAME) == null) {

         sharedState.put(AbstractLoginModule.NAME, userName);

         nameSet = true;

      }

 

      successful = true;

      return true;

   }

 

  /**

   * Commit the login. This is the second part of the authentication

   * process.

   * If a user name has been stored by the login() method,

   * the user name is added to the subject as a new principal.

   */

   public boolean commit() throws LoginException {

 

      if (successful) {

 

         /* The principals that are added to the subject should

          * implement java.security.Principal.You can use the class

          * com.sap.engine.lib.security.Principal for this purpose.

          */

         Principal principal = new Principal(userName);

         subject.getPrincipals().add(principal);

 

         /* If the login is successful, then the principal corresponding

          * to the <userName> (the same user name that has been added

          * to the subject) must be added in the shared state too.

          * This principal is considered to be the main principal

          * representing the user.

          * For example, this principal will be retrieved from method

          * getUserPrincipal() of the HTTP request.

          */

 

         if (nameSet) {

            sharedState.put(AbstractLoginModule.PRINCIPAL, principal);

         }

      } else {

         userName = null;

      }

      return true;

   }

 

   /**

    * Abort the authentication process.

    */

   public boolean abort() throws LoginException {

 

      if (successful) {

         userName = null;

         successful = false;

      }

 

      return true;

   }

 

   /**

    * Log out the user. Also removes the principals and

    * destroys or removes the credentials that were associated 

    * with the user during the commit phase.

    */

   public boolean logout() throws LoginException {

     

      // Remove principals and credentials from subject

      if (successful) {

         subject.getPrincipals(Principal.class).clear();

         successful = false;

      }

     

      return true;

   }

}

 

End of Content Area