Puntos de personalización LDAP

Existen puntos de personalización disponibles cuando se integra con LDAP para manejar lógica de sincronización adicional.

Un mandato de tarea nuevo denominado com.ibm.commerce.member.syncbeans.commands.LDAPIntegrationCmd contiene métodos que se pueden alterar temporalmente. Puesto que la integración LDAP requiere una implementación de todo el sitio, únicamente se puede registrar una implementación de esta mandato utilizando la tienda 0.

Los métodos se llaman en diferentes puntos en escenarios de integración LDAP:

Soporte para diferentes jerarquías organizativas en LDAP y la base de datos de HCL Commerce

Es recomendable que la estructura de la organización y los nombres distinguidos del servidor LDAP coincidan con lo que hay en la base de datos de HCL Commerce. Si las jerarquías de organización coinciden, pero los nombres distinguidos de la organización raíz y la organización predeterminada en LDAP son diferentes de los valores predeterminados en HCL Commerce, el asistente de integración puede manejar la redenominación de los valores DN en HCL Commerce durante la configuración inicial de HCL Commerce con LDAP. No obstante, si las jerarquías de organización son diferentes, por ejemplo el servidor LDAP tiene una estructura relativamente plana mientras que la base de datos de HCL Commerce tiene una estructura más compleja, el método recomendado sigue siendo crear la estructura LDAP igual que la estructura organizativa de HCL Commerce. No obstante, si esto no es posible, debe sustituir la implementación predeterminada de los métodos siguientes del mandato de tarea LDAPIntegrationCmd para manejar la correlación entre los DN de LDAP y los DN de la base de datos de HCL Commerce:

public String getLDAPDN(String astrCommerceDN) throws ECException; 

public String getCommerceDN(String astrLDAPDN, DataObject adoMember) throws ECException; 

Si la correlación entre los DN de organización es de una a varias, por ejemplo una organización en LDAP se correlaciona con varias organizaciones compradoras en HCL Commerce, estas organizaciones deben cargarse previamente manualmente en ambos sistemas, en lugar de basarse en OrganizationSyncBean para crearlas automáticamente.

En todos los casos, HCL Commerce requiere que la organización raíz (-2001) sea el predecesor común de todas las demás organizaciones y la organización predeterminada (-2000) exista directamente bajo la organización raíz. HCL Commerce espera que la Organización predeterminada sea la organización padre de clientes de B2C.

Ejemplo

/**
* Returns the LDAP DN that corresponds to a specified Commerce DN.
* By default, the following mapping is done: <ul>
* <li> "uid=xxx,o=buyer a organization,o=root organization" maps to "uid=xxx,o=internal,o=root organization"
*
* <li> "uid=yyy,o=buyer b organization,o=root organization" maps to "uid=yyy,o=internal,o=root organization"
*
* <li> DNs ending with "o=default organization,o=root organization" are changed to end with "o=testorg,o=root organization"
*
* <li> Otherwise, the input DN is returned.
* </ul>
*
* @param astrCommerceDN The Commerce DN.
* @return The LDAP DN.
* @exception ECException Thrown if an error occurs.
*/
public String getLDAPDN(String astrCommerceDN) throws ECException {

String strLDAPDN = astrCommerceDN;

if (astrCommerceDN.equals(BUYER_A_ORG_DN) ||
astrCommerceDN.equals(BUYER_B_ORG_DN) ) {

//Map "o=buyer x organization,o=root organization" to "o=internal,o=root organization"
strLDAPDN = INTERNAL_ORG_DN;
} else if ( astrCommerceDN.indexOf(BUYER_A_ORG_DN) > 0) {
int nIndex = astrCommerceDN.indexOf(BUYER_A_ORG_DN);
String strDNBeginning = astrCommerceDN.substring(0, nIndex);

//Map "uid=yyy,o=buyer a organization,o=root organization" to "uid=yyy,o=internal,o=root organization"

strLDAPDN = strDNBeginning + INTERNAL_ORG_DN;

} else if ( astrCommerceDN.indexOf(BUYER_B_ORG_DN) > 0) {
int nIndex = astrCommerceDN.indexOf(BUYER_B_ORG_DN);
String strDNBeginning = astrCommerceDN.substring(0, nIndex);

//Map "uid=yyy,o=buyer b organization,o=root organization" to "uid=yyy,o=internal,o=root organization"

strLDAPDN = strDNBeginning + INTERNAL_ORG_DN;

} else if ( astrCommerceDN.endsWith("o=default organization,o=root organization")) {
strLDAPDN = SyncBeanUtil.getRDN(astrCommerceDN)
+ ECMemberConstants.EC_LDAP_DN_SEPARATOR
+ "o=testorg,o=root organization";
}

return strLDAPDN;
}


/**
* Returns the Commerce DN that corresponds to a specified LDAP DN: <ul>
*
* <li> If the user belongs to the "buyer x organization" member
* group in LDAP, then the user belongs to "buyer x organization" in Commerce.
*
* <li> DNs ending with "o=default organization,o=root organization" are changed to end with "o=testorg,o=root organization"
*
* <li> Otherwise, the input DN is returned.
* </ul>
*
* @param astrLDAPDN The LDAP DN.
* @param adoMember The entity data object corresponding to the member.
* @return The Commerce DN.
* @exception ECException Thrown if an error occurs.
*/
public String getCommerceDN(String astrLDAPDN, DataObject adoMember)
throws ECException {

String strCommerceDN = astrLDAPDN;

if (astrLDAPDN.endsWith(INTERNAL_ORG_DN)) {

/**
* Get the group information for the user.
* If the user belongs to the "buyer x organization" member
* group in LDAP, then the user belongs to "buyer x
* organization" in Commerce, etc.
*/
List<DataObject> lstGroups = adoMember.getList( SchemaConstants.DO_GROUPS);
Iterator<DataObject> iterGroups = lstGroups.iterator();
while (iterGroups.hasNext()) {
DataObject doGroup = iterGroups.next();
DataObject doID = doGroup.getDataObject(SchemaConstants.DO_IDENTIFIER);
String strGroupName = doID.getString(SchemaConstants.PROP_UNIQUE_NAME);

if ( BUYER_A_MBRGRP_DN.equals(strGroupName) ) {

strCommerceDN = SyncBeanUtil.getRDN(astrLDAPDN)
+ ECMemberConstants.EC_LDAP_DN_SEPARATOR
+ BUYER_A_ORG_DN;

break;
} else if (BUYER_B_MBRGRP_DN.equals(strGroupName) ) {

strCommerceDN = SyncBeanUtil.getRDN(astrLDAPDN)
+ ECMemberConstants.EC_LDAP_DN_SEPARATOR
+ BUYER_B_ORG_DN;

break;
}
}
} else if (astrLDAPDN.endsWith("o=testorg,o=root organization")) {
strCommerceDN = SyncBeanUtil.getRDN(astrLDAPDN)
+ ECMemberConstants.EC_LDAP_DN_SEPARATOR
+ "o=default organization,o=root organization";
}
return strCommerceDN;
} 

Comentario emergente para realiza proceso adicional durante un inicio de sesión único en (SSO) y conexión

En LogonCmdImpl.java, cuando la modalidad de autenticación se establece en LDAP y la autenticación es correcta, se llama al método siguiente de LDAPIntegrationCmdImpl.java para permitir que se realice un proceso adicional:

public void postLogonProcessing(UserAccessBean aUserAccessBean) throws ECException;
UserSyncBean.findByMemberId(aUserAccessBean.getMemberId()) se puede llamar para obtener UserSyncBean. En UserSyncBean.getLDAPMember() devuelve un DataObject que representa el objeto en LDAP, que se puede utilizar para proceso adicional.
Después de que se realice un inicio de sesión único, se llama al método siguiente para manejar cualquier proceso adicional:

public void postSingleSignOnProcessing(UserSyncBean aUserSyncBean) throws ECException;

Utilizar la información de grupo de miembros de usuarios en LDAP

El ejemplo de implementación siguiente muestra cómo la información de grupo de miembros de un usuario en LDAP se puede utilizar para asignar roles al usuario en HCL Commerce:
/**
 * This method is called after single sign-on has taken place.
 * It enables extra processing to take place. 
 *
 * Behavior: 
 * 
 *
 * Get the LDAP groups that the user belongs to from the UserSyncBean's LDAP data object.
 * 
 * If the user belongs to the "cn=csr,cn=groups,o=root organization" LDAP group, assign 
 * them the CSR role in Root Organization, if they don't have that role already.
 * 
 * If the user belongs to the "cn=gold customers,cn=groups,o=root organization" LDAP 
 * group, include them in the corresponding WC member group: "gold customers", if they 
 * don't already belong to it.
 * 
 * @param aUserSyncBean Contains information about the user that has authenticated. 
 * @throws ECException Thrown if an error occurs.
 */
public void postSingleSignOnProcessing(UserSyncBean aUserSyncBean) throws ECException{

  final String METHODNAME = "postSingleSignOnProcessing(UserSyncBean aUserSyncBean)";

  DataObject doLDAPMember = aUserSyncBean.getLDAPMember();

  if (doLDAPMember == null) {
    return;
  }

  //Get the groups that the user belongs to in LDAP
  List<DataObject> lstGroups = doLDAPMember.getList( SchemaConstants.DO_GROUPS);
  Iterator<DataObject> iterGroups = lstGroups.iterator();

  //Get the groups the user belongs to and then synch to WC DB's MBRROLE or MBRGRPMBR
  while (iterGroups.hasNext()) {
    DataObject doGroup = iterGroups.next();
    DataObject doID = doGroup.getDataObject(SchemaConstants.DO_IDENTIFIER);
    String strGroupName = doID.getString(SchemaConstants.PROP_UNIQUE_NAME);

    try{
      if ("cn=csr,cn=groups,o=root organization".equals(strGroupName)) {
        //Assign the user the CSR role in the Root Organization
        try {
          MemberRoleCache.findByMemberIdRoleIdOrgEntityId(
              Long.valueOf(aUserSyncBean.getMemberId()), 
              CSR_ROLE,
              ROOT_ORG);
        } catch (FinderException e) {
          // Role assignment does not exist, so create it
          new MemberRoleAccessBean(
              Long.valueOf(aUserSyncBean.getMemberId()), 
              CSR_ROLE,
              ROOT_ORG);
        } 
      } else if (GOLD_CUST_LDAP_GROUP.equals(strGroupName)) {

        MemberGroupAccessBean abMbrGrp = null;
        try {
          abMbrGrp = MemberGroupCache.findByOwnerName(
              ROOT_ORG, 
              GOLD_CUST_WC_GROUP);
        } catch (FinderException e) {
          ECTrace.trace(ECTraceIdentifiers.COMPONENT_USER, CLASSNAME, METHODNAME,
              "Member group does not exist: " + GOLD_CUST_LDAP_GROUP);

          continue; // skip to next iteration in the loop
        }


        //Assign the user to this member group in Commerce if it doesn't already exist
        try {
          MemberGroupMemberCache.findByPrimaryKey(
              abMbrGrp.getMbrGrpId(), 
              aUserSyncBean.getMemberId());
        } catch (FinderException e) {
          //Since the user doesn't belong to member group, add it now
          new MemberGroupMemberAccessBean(
              abMbrGrp.getMbrGrpIdInEJBType(), 
              Long.valueOf(aUserSyncBean.getMemberId()));
        }

      }
    } catch (NamingException e) {
      throw new ECSystemException(
          ECMessage._ERR_NAMING_EXCEPTION, 
          CLASSNAME, 
          METHODNAME, 
          ECMessageHelper.generateMsgParms(e), 
          e);
    } catch (RemoteException e) {
      throw new ECSystemException(
          ECMessage._ERR_REMOTE_EXCEPTION, 
          CLASSNAME, 
          METHODNAME, 
          ECMessageHelper.generateMsgParms(e), 
          e);
    } catch (CreateException e) {
      throw new ECSystemException(
          ECMessage._ERR_CREATE_EXCEPTION, 
          CLASSNAME, 
          METHODNAME, 
          ECMessageHelper.generateMsgParms(e), 
          e);
    } catch (FinderException e) {
      throw new ECSystemException(
          ECMessage._ERR_FINDER_EXCEPTION, 
          CLASSNAME, 
          METHODNAME, 
          ECMessageHelper.generateMsgParms(e), 
          e);
    }
  }
} 

Comentario emergente para proceso adicional en SyncBean

El método siguiente se puede sustituir para realizar proceso adicional cuando LDAP se está actualizando mediante un bean sincronización:

public void LDAPIntegrationCmd.postUpdateToLDAP (UserSyncBean userSyncBean) throws ECException;
El método siguiente se puede sustituir para realizar proceso adicional cuando datos de LDAP estén actualizando la base de datos de HCL Commerce:

public void LDAPIntegrationCmd.postRefreshFromLDAP (UserSyncBean userSyncBean) throws ECException;

Sincronizar datos adicionales

UserSyncBean y OrganizationSyncBean leen y escriben datos a la base de datos así como a LDAP. Cada clase lee y escribe en un conjunto predeterminado de tablas de base de datos de HCL Commerce. Cada una de estas tablas tiene una clase de objeto de datos de ayuda de sincronización (DO) que el bean de sincronización utiliza para leer y escribir en la tabla:
UserSyncBean
Clase DO Tabla de base de datos
UserDO USERS
UserRegistryDO USERREG
UserDemographicsDO USERDEMO
SelfAddressDO ADDRESS (SELF ADDRESS)
BusinessProfileDO BUSPROF
UserProfileDO USERPROF
MemberAttributesDO MBRATTRVAL
OrganizationSyncBean
Clase DO Tabla de base de datos
OrgEntityDO ORGENTITY
SelfAddressDO ADDRESS (SELF ADDRESS)
MemberAttributesDO MBRATTRVAL
Las clases DO que hay que incluir para cada bean de sincronización pueden especificarse y cambiarse desde la implementación predeterminada. Por ejemplo, a continuación se muestra la implementación predeterminada de LDAPIntegrationCmd.getUserDOs():

public Vector getUserDOs() {
        
        Vector vUserDOs = new Vector(7);
        
        vUserDOs.add(new UserDO());
        vUserDOs.add(new UserRegistryDO());
        vUserDOs.add(new UserDemographicsDO());
        vUserDOs.add(new SelfAddressDO());
        vUserDOs.add(new BusinessProfileDO());
        vUserDOs.add(new UserProfileDO());
        vUserDOs.add(new MemberAttributesDO());
        
        return vUserDOs;
    }
El mandato de tarea se puede ampliar y se pueden ampliar más clases DO si desea sincronizarlas con nuevas tablas de usuarios personalizados.
A continuación se muestra la implementación predeterminada de LDAPIntegrationCmd.getOrganizationDOs():

public Vector getOrganizationDOs() {
        
        Vector vUserDOs = new Vector(3);
        
        vUserDOs.add(new OrgEntityDO());
        vUserDOs.add(new SelfAddressDO());
        vUserDOs.add(new MemberAttributesDO());
        
        return vUserDOs;
    }
Igual que en el ejemplo anterior, el mandato de tarea se puede ampliar y se pueden añadir más clases DO si desea sincronizarlas con nuevas tablas de organización predeterminadas.