Los lectores frecuentes del blog de Zimbra sabrán que Zimbra se puede ampliar/personalizar mediante el uso de Zimlets. Al crear sus propios Zimlets, puede agregar funcionalidad a la interfaz de usuario (front-end) y al back-end de Java, lo que le permite satisfacer las necesidades específicas de los clientes. Los Zimlets se pueden habilitar globalmente o por usuario (grupo)
Los detalles sobre esto se pueden encontrar en nuestra wiki: https://wiki.zimbra.com/wiki/DevelopersGuide y https://blog.zimbra.com/2020/05/zimbra-skillz-extending-zimbras-backend-functionality- con-zimlets/
En este blog aprenderás:
En Internet se pueden encontrar muchos ejemplos para hacer esto, pero la mayoría de los ejemplos están incompletos y/o son inseguros, por lo que incluso si ya implementó Zimbra o la autenticación LDAP externa en Java anteriormente, lea el resto del blog y valide su implementación.
Implementando la autenticación Zimbra en una extensión Zimbra
Si echamos un vistazo a la extensión de ejemplo en: https://github.com/Zimbra/zm-extension-guide/blob/master/src/com/example/mytest/Mytest.java#L55 verás que hay no se necesita autenticación en el método doGet . doGet es lo que implementamos para manejar solicitudes HTTP GET en extensiones de Zimbra.
Puede utilizar la siguiente API Java de Zimbra como contenedor para implementar la autenticación de Zimbra:
public void doGet(HttpServletRequest req, HttpServletResponse resp) lanza IOException, ServletException {n final AuthToken authToken = AuthUtil.getAuthTokenFromHttpReq(req, resp, false, true);n si (authToken! = nulo) {n //Este código sólo es accesible para usuarios autenticadosn }n demásn {n //Hacer algo para los usuarios no autenticadosn }n}
Si también desea implementar una verificación CSRF, puede consultar: https://github.com/Zimbra/zm-extension-guide/blob/master/Implementing%20a%20CSRF%20check%20on%20a%20Zimbra% 20extensión.md
Hay muchos otros ejemplos en el (antiguo) código Zimbra en Internet, la mayoría de las veces tendrán algún iterador que encuentra la cookie de autenticación de Zimbra y luego valida la cookie y obtiene una Clase de servicio u otro parámetro de cuenta. Muchos de estos ejemplos carecen de una o más validaciones de autenticación, como caducidad de contraseña, bloqueo de cuenta, etc. Se recomienda el uso de AuthUtil.getAuthTokenFromHttpReq ya que esta es la API diseñada e implementa la verificación completa de autenticación de Zimbra.
Implementación de autenticación LDAP externa en Java
Para la autenticación LDAP externa utilizamos API de Java salientes, es decir, no específicas de Zimbra. Puede implementar una verificación de nombre de usuario/contraseña en un servidor LDAP externo de la siguiente manera:
autenticación booleana estática pública (nombre de usuario de cadena, contraseña de cadena) {n intentarn {n if (StringUtils.isEmpty(contraseña) || StringUtils.isBlank(contraseña)) {n ZimbraLog.account.info("Error de autenticación de contraseña");n falso retorno;n }n si (contraseña.longitud() < 10) {n ZimbraLog.account.info("contraseña demasiado corta, longitud mínima: 10");n falso retorno;n }nn // Configurar el entorno para crear el contexto inicialn Hashtable<String, String> env = new Hashtable<>();n env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");n env.put(Context.PROVIDER_URL, "ldap://myldap.example.com:389");n LdapContext ctx = nuevo InicialLdapContext(entorno, nulo);n StartTlsResponse tls;n intentar {n tls = (StartTlsResponse) ctx.extendedOperation(new StartTlsRequest());n tls.negociar();n } captura (Excepción e) {n ZimbraLog.account.info("Mi extensión Zimbra informa: falla LDAP TLS");n falso retorno;n }nn // Realizar autenticación de cliente simplen ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");n ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, DNify(nombre de usuario));n ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, contraseña);n ZimbraLog.account.debug(ctx.lookup(DNify(nombre de usuario))); // ¡Esto generará una excepción cuando falle la autenticación!n tls.close();n ctx.close();nn //Si estamos aquí, el nombre de usuario/contraseña pasado es correcto y podemos proceder a obtener el objeto de cuenta Zimbra.n Cuenta cuenta = Provisioning.getInstance().getAccountByName(nombre de usuario);n //haz algo aquín devolver verdadero;n } captura (Excepción e) {n ZimbraLog.account.info("Error de autenticación de contraseña LDAP");n falso retorno;n }n falso retorno;n }nn /* Convertir la dirección de correo electrónico a DN, ¿hay alguna forma mejor?n System.out.println(DNify("info.urft@mail.barrydegraaff.nl"));n huellas dactilares:n uid=info.urft,ou=personas,dc=correo,dc=barrydegraaff,dc=nln * */n cadena estática pública DNify (cadena de correo electrónico) {n Cadena[] dividir = email.split("@");n return "uid=" + split[0] + ",ou=people,dc=" + split[1].replaceAll("\\.", ",dc=");n }n
Ver también: https://docs.oracle.com/javase/jndi/tutorial/ldap/ext/starttls.html
El ejemplo de autenticación LDAP anterior forzará el uso de STARTTLS en la conexión entre Zimbra y su servidor LDAP. Muchos ejemplos en Internet usarán algo como:
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");nenv.put(Context.PROVIDER_URL, "ldap://myldap.example.com:389");n...nenv.put(Context.SECURITY_PROTOCOL, "ssl");nDirContext ctx = nuevo InicialDirContext(entorno);
Esto NO forzará el uso de STARTTLS o TLS.
Al utilizar StartTlsResponse, el cliente LDAP de Java ( com.sun.jndi.ldap.LdapCtxFactory ) no puede recurrir a la comunicación de texto sin formato. Lo que significa que se utilizará TLS entre su aplicación Java y el servidor LDAP. Si STARTTLS falla, se generará una excepción y la autenticación fallará independientemente de si el usuario ingresó un nombre de usuario/contraseña correcto.