ATLAS MANUAL DE INTEGRACIÓN Servicios de Firma AFC Cliente Versión 1.3 Arquitectura de Software Framework Atlas Servicios de Firma AFC Cliente Hoja de Control Título Servicios de Firma AFC Cliente Documento de Referencia NORMATIVA ATLAS Responsable Arquitectura de Software Versión 1.3 Fecha Versión 13/11/2015 Registro de Cambios Versión Causa del Cambio 1.0 Versión inicial del documento Responsable del Cambio Fecha del Cambio Unidad de Arquitectura Revisión del documento. 1.1 06/02/2014 Unidad de Arquitectura 26/03/2014 Añadida información sobre Tipo de presentación de Unidad de Arquitectura 23/09/2014 Añadidos ejemplos de firma CADES. Añadido opción de uso de @PostConstruct 1.2 ventana flotante Añadida nota sobre variables y configuración de Spring sobrante a partir de versión de atlas 1.2.8 1.3 Añadida información sobre presentación 4 Uso de nueva librería crypt 2 de 43 Unidad de Arquitectura 13/11/2015 Framework Atlas Servicios de Firma AFC Cliente Índice 1. INTRODUCCIÓN ................................................................................................................................................................ 4 1.1. AUDIENCIA OBJETIVO ...................................................................................................................................................... 5 2. DESCRIPCIÓN .................................................................................................................................................................... 6 3. EJEMPLOS ........................................................................................................................................................................... 7 4. INSTALACION Y CONFIGURACION............................................................................................................................. 8 4.1. ALTA EN AFC ............................................................................................................................................................... 8 4.2. CONFIGURACION ....................................................................................................................................................... 9 4.2.1. Configuración de acceso a AFC ............................................................................................................................. 9 4.2.2. Configuración de acceso a COVE ....................................................................................................................... 10 4.3. INSTALACION ............................................................................................................................................................ 10 4.3.1. Paso 1: Añadir la dependencia al módulo de Administración Electrónica .......................................................... 10 4.3.1. Paso 2: Actualizar la configuración de Spring ..................................................................................................... 11 5. USO ....................................................................................................................... ¡ERROR! MARCADOR NO DEFINIDO. 5.1. FIRMA DOCUMENTOS PDF ..................................................................................................................................... 12 5.1.1. Solicitar url de Firma ............................................................................................. ¡Error! Marcador no definido. 5.1.2. Realizar llamada a AFC ....................................................................................................................................... 18 5.1.3. Opción de presentación 3 ..................................................................................................................................... 18 5.1.4. Recibir la respuesta de la firma. ........................................................................................................................... 23 5.1.5. Recepción de respuesta con anotación @PostConstruct ...................................................................................... 25 5.2. FIRMA MASIVA DOCUMENTOS PDF ............................................................... ¡ERROR! MARCADOR NO DEFINIDO. 5.2.1. Implementación de la Interfaz PdfFileProvider .................................................................................................... 28 5.2.2. Selección del certificado cliente para la firma ..................................................................................................... 33 Solicitud de firma .................................................................................................................... ¡Error! Marcador no definido. 5.2.3. Recibir la respuesta de las firmas. ........................................................................................................................ 37 5.2.4. Recogida de firmas y procesado de las mismas .................................................................................................... 37 5.3. FIRMA INDIVIDUAL DOCUMENTOS XML ........................................................................................................... 39 5.4. FIRMA MASIVA DOCUMENTOS XML ................................................................................................................... 40 5.5. FIRMA INDIVIDUAL CADES.................................................................................................................................... 40 5.6. FIRMA MASIVA CADES ........................................................................................................................................... 42 ENLACES RELACIONADOS .................................................................................................................................................. 43 3 de 43 Framework Atlas Servicios de Firma AFC Cliente 1. INTRODUCCIÓN AFC es la solución de firma centralizada para las aplicaciones de la Comunidad de Madrid. Objetivos buscados: Operativo de firma similar y centralizada. Formatos comunes de firma compatibles con ENI (Esquema Nacional de Interoperabilidad) Simplificar la integración de requisitos de firma en los desarrollos. Transparencia en las actualizaciones de la plataforma de firma Inventario de aplicaciones y tipos de firmas Histórico y estadísticas de operaciones realizadas Operaciones que permite: Firma digital en cliente Firma digital en servidor Validación de firmas Estado de certificados Datos de certificados Tipos de firma (Admitidos por el ENI) PADES – PDF Advanced Electronic Signature XADES – XML Advanced Electronic Signature CADES – CMS Advanced Electronic Signature Integración: La integración con la solución de AFC se realiza a través de la librería del Framework Atlas atlasfrm_eadm (librería que conecta con los servicios de administración electrónica) hasta la versión 1.2.8, a partir de la versión 1.2.9 se utilizará la librería atlasfrm_crypt. Esta librería puede ser utilizada tanto por aplicaciones desarrolladas con el framework Atlas así como las desarrolladas con otros frameworks Java (framework 2 o framework Justicia). Dentro de esta librería podemos encontrar tres servicios: AfcOpeClienteService: Servicio de Operaciones en cliente AfcOpeServidorService: Servicio de Operacion en servidor AfcOpeCertificadoService: Servicio de Operaciones con certificado Este documento describe el servicio de afc para operaciones en cliente. Si se va a utilizar desde una aplicación que no es del framework ATLAS consultar el manual FW2_MUS_Integracion_AFC. 4 de 43 Framework Atlas Servicios de Firma AFC Cliente 1.1. Audiencia objetivo Este documento está orientado a desarrolladores java que necesiten realizar operaciones de firma en cliente. 5 de 43 Framework Atlas Servicios de Firma AFC Cliente 2. DESCRIPCIÓN Las operaciones que el servicio de afc ofrece en cliente son: Firma individual de documentos: Se envía un documento integro a la firma. Firma masiva de documentos: esta operación está especialmente diseñada para la firma de varios documentos a la vez. En el caso de ficheros pdf el proceso se ha optimizado para que no sea necesaria la transferencia de estos ficheros con el consiguiente ahorro de recursos. En lugar de enviar los ficheros a la firma se enviará un hash de cada uno de los ficheros. Esta operación también es recomendada para la firma de ficheros Pdf pesados aunque la firma sea individual En el caso de ficheros pdf, la operativa actual permite obtener e insertar en el documento el código COVE para su visualización pública. A continuación se muestra un gráfico simplificado de la operativa de firma entre la aplicación del usuario de firma y AFC Cliente: APLICACION AFCSERVICE AFC_FIRMACLIENTE SOLICITAR URL FIRMA REDIRIGIR RECOGER ERRORES RECOGER FIRMA 1. Solicitar url firma: en este momento se ejecutará una llamada al servicio de AFC con una solicitud de una operación de firma. El servicio responderá con una URL a la que deberá redirigirse al usuario para la ejecución de la operación. 2. Redirigir usuario a AFC_FIRMACLIENTE: en este punto, la aplicación cliente deberá redirigir al usuario a la URL obtenida en el punto anterior. En esta aplicación el usuario podrá realizar la firma digital del documento o documentos solicitados. Una vez concluida la firma, se devolverá al usuario a la URL de retorno configurada en el paso 1 (solicitud de firma). 3. Recoger firmas/errores: si la operación de firma ha ido bien, la aplicación cliente solicitará al servicio de AFC los documentos firmados por el usuario. En caso contrarió solicitará los errores generados en la firma. 6 de 43 Framework Atlas Servicios de Firma AFC Cliente 3. EJEMPLOS Se han desarrollado varios ejemplos para ver la integración en los distintos frameworks: Aplicación ATLAS : afc_demo: https://desarrollo.madrid.org/afc_demo Aplicación ATLAS : atlas_integracion_asf: https://desarrollo.madrid.org/atlas_integracion_asf Aplicación Framework 2: ejpl_crypto_web: http://desarrollo.madrid.org/ejpl_crypto_web 7 de 43 Framework Atlas Servicios de Firma AFC Cliente 4. INSTALACION Y CONFIGURACION 4.1. ALTA EN AFC Antes de utilizar el servicio de AFC en desarrollo es necesario autorizar a la aplicación. Las peticiones de autorización de uso del servicio AFC se dirigirán a través del servicio Remedy al grupo GC.AE. Para firma en cliente es necesario indicar en la petición los siguientes datos: Aplicación: Código poaps del proyecto Nombre del módulo técnico: Nombre del modulo técnico que se va a integrar con AFC. Este valor será el que se informará en el fichero de configuración de la aplicación en la propiedad afc.modulo. Descripción uso: Breve descripción del uso que se requiere del servicio AFC Entorno: Entorno donde se requiere la autorización Login administrador: Usuario con el que acceder al entorno AFC para la administración de documentos Para cada tipo de documento a firmar - Nombre del tipo de documento - Formato: XADES, PADES o CADES - En caso de firma PADES si se incluye código de COVE o no - Número de firmas - Tipo de firma: Integra o Hash - Por cada firma: o Fuente: Por defecto Arial 8 o Firma visible o no: Por defecto No o En caso de firma visible información acerca de la ubicación de la firma.(coordenadas y página) o Descripcion del firmante Una vez que se autorice su uso se recibirá una password (diferente para cada entorno) que habrá que informar en el fichero de configuración en la variable afc.password. 8 de 43 Framework Atlas Servicios de Firma AFC Cliente 4.2. CONFIGURACION 4.2.1. Configuración de acceso a AFC La información de acceso se definirán en el fichero de configuración mediante las siguientes variables (el nombre de estas variables es igual para todos los frameworks): Variable afc.modulo Descripción Nombre del módulo para autenticarse contra el servicio de Obligatorio SI ASF. Se corresponde con el nombre dado de alta en el Servicio de ASF. afc.password Contraseña de acceso, debe estar cifrada. Esta contraseña SI se proporciona cuando se solicita el acceso al Servicio de AFC. A continuación se muestra un ejemplo de configuración. Ejemplo de configuracion # Configuracion de acceso a AFC_Cliente afc.modulo=ejpl_app afc.password=98D943B7C420E3F9 # Opcionalmente se puede incluir información del tipo de documento a firmar si la aplicación solamente trabaja con un tipo de documento afc.documentoTipo=SolicitudAyuda afc.numeroFirma=1 9 de 43 Framework Atlas Servicios de Firma AFC Cliente 4.2.2. Configuración de acceso a COVE Si los documentos a firmar han de incluir el código de COVE es necesario especificar en el fichero de configuración la información de acceso al Servicio de Administración Electrónica COVE. Las variables que es necesario configurar son las siguientes (el nombre de las variables es el mismo para todos los frameworks): Variable Descripción cove.aplicacion Aplicación que accede al sistema COVE cove.tipo Código del Tipo de certificado a utilizar cove.usuario Usuario que accede al sistema COVE A continuación se muestra un ejemplo de configuración. Ejemplo de configuración # Configuracion de acceso a COVE cove.usuario=UUIA01 cove.tipo=EJARCH cove.aplicacion=EJPL 4.3. INSTALACION El Servicio de AFC Cliente viene incluido en el módulo de Encryptación de Atlas. Para poder utilizarlo, bastará con incluir la dependencia de este módulo en el fichero pom.xml del proyecto, añadir un import del fichero applicationContext-crypt-lib.xml, y definir en el contexto de Spring la configuración del servicio para la aplicación. 4.3.1. Paso 1: Añadir la dependencia al módulo de Encryptación de atlas Para añadir la dependencia al módulo de Encriptación (crypt-lib) dentro de nuestro proyecto maven hay que añadir una entrada “dependency” en la sección “dependencies” del fichero “pom.xml” del proyecto, como se puede ver en el siguiente ejemplo: 10 de 43 Framework Atlas Servicios de Firma AFC Cliente pom.xml <dependencies> … <dependency> <groupId>atlasfrm</groupId> <artifactId>atlasfrm-crypt-lib</artifactId> <version>${atlasfrm-crypt-lib.version}</version> </dependency> </dependencies> 4.3.1. Paso 2: Actualizar la configuración de Spring Es necesario importar la configuración de Spring para los servicios de la librería crypt dentro del fichero applicationContext-services.xml. applicationContext-services.xml <import resource="classpath:/conf/applicationContext-crypt-lib.xml" /> 11 de 43 Framework Atlas Servicios de Firma AFC Cliente 5. OPERACIONES DE FIRMA Una vez configurada la aplicación se puede proceder a utilizar todas las funcionalidades que ofrece. 5.1. FIRMA DOCUMENTOS PDF - PADES Para realizar firmas de documentos del tipo PADES, existen 2 métodos, firma Individual: AfcOpClienteService /** * Solicita a AFC una operación de firma individual. * @param data contenido del documento a firmar * @param signInfo información de acceso a AFC. * @param loginCert certificado de login de usuario * @param opcionesPresentacion tipo de presentación del documento en AFC * @param urlOk url de retorno a la aplicación en una operación de firma correcta. * @param urlError url de retorno a la aplicación en una operación de firma incorrecta. * @return identificador de la operación en AFC (para recoger las firmas). * @throws ServiceException si hubo problemas */ <E extends Serializable> String solicitarFirmaIndividual(byte[] data, SignInfo<E> signInfo, X509Certificate loginCert, String opcionesPresentacion, String urlOk, String urlError) throws ServiceException; Parámetro Descripción byte[] data Fichero a firmar SignInfo signInfo Información de firma para el servicio de AFC X509Certificate loginCert Certificado con el que se ha logado en la aplicación. Si no hay certificado se pone null. String opcionesPresentacion Opción de presentación: 1.- Se muestra el contenido del documento embebido en la página de la firma 2.- Se muestra una lista con el fichero a firmar y la posibilidad de pinchar en un enlace para visualizar el documento 3.- Modo ventana flotante. 4.- Modo ventana flotante directa. String urlOk Url a la que redirigir al final de la firma si todo a ido bien String urlError Url a la que redirigir al final de la firma si se ha producido algún error Firma Masiva de documentos: 12 de 43 Framework Atlas Servicios de Firma AFC Cliente AfcOpClienteService /** * Solicita a AFC una operación de firma masiva Pdf. * @param provider proveedor de ficheros para la operación de firma * @param loginCertificate certificado de login de usuario * @param urlOk url de retorno a la aplicación en una operación de firma correcta. * @param urlError url de retorno a la aplicación en una operación de firma incorrecta. * @return identificador de la operación en AFC (para recoger las firmas). * @throws ServiceException si hubo problemas */ <E extends Serializable> String solicitarFirmaPdfMasiva(PdfFileProvider<E> provider, X509Certificate loginCertificate, String opcionesPresentacion, String urlOk, String urlError) throws ServiceException; Parámetro 5.2. Descripción Objeto FileProvider FileProvider con todos los ficheros a firmar X509Certificate loginCert Certificado con el que se ha logado en la aplicación. Si no hay certificado se pone null. String opcionesPresentacion Opción de presentación: 1.- Se muestra el contenido del documento embebido en la página de la firma 2.- Se muestra una lista con el fichero a firmar y la posibilidad de pinchar en un enlace para visualizar el documento 3.- Modo ventana flotante 4.- Modo ventana flotante directa String urlOk Url a la que redirigir al final de la firma si todo a ido bien String urlError Url a la que redirigir al final de la firma si se ha producido algún error FIRMA DOCUMENTOS XML – XADES Para realizar la firma de ficheros XML, existen 2 métodos, para firmas individuales: AfcOpClienteService 13 de 43 Framework Atlas Servicios de Firma AFC Cliente /** * Solicita a AFC una operación de firma individual. * @param data contenido del documento a firmar * @param signInfo información de acceso a AFC. * @param loginCert certificado de login de usuario * @param opcionesPresentacion tipo de presentación del documento en AFC * @param urlOk url de retorno a la aplicación en una operación de firma correcta. * @param urlError url de retorno a la aplicación en una operación de firma incorrecta. * @return identificador de la operación en AFC (para recoger las firmas). * @throws ServiceException si hubo problemas */ <E extends Serializable> String solicitarFirmaIndividual(byte[] data, SignInfo<E> signInfo, X509Certificate loginCert, String opcionesPresentacion, String urlOk, String urlError) throws ServiceException; Y el método para firmas masivas: AfcOpClienteService /** * Solicita a AFC una operación de firma masiva XAdES * @param xmls ficheros a firmar * @param loginCertificate certificado de acceso para filtrado en selección * @param urlOk url de retorno a la aplicación en una operación correcta. * @param urlError url de retorno a la aplicación en una operación incorrecta. * @return url de acceso a la aplicación de firma al que redirigir al usuario * @throws ServiceException si hubo problemas */ <E extends Serializable> String solicitarFirmaXadesMasiva(Map<SignInfo<E>, byte[]> xmls, X509Certificate loginCertificate, String opcionesPresentacion, String urlOk, String urlError) throws ServiceException; Parámetro Descripción Map <SignInfo<E>, byte[]> Mapa con los ficheros a firmar y la información de AFC necesaria para realizar la firma X509Certificate loginCert Certificado con el que se ha logado en la aplicación. Si no hay certificado se pone null. String opcionesPresentacion Opción de presentación: 1.- Se muestra el contenido del documento embebido en la página de la firma 2.- Se muestra una lista con el fichero a firmar y la posibilidad de pinchar en un enlace para visualizar el documento 3.- Modo ventana flotante 4.- Modo ventana flotante directa String urlOk Url a la que redirigir al final de la firma si todo a ido bien 14 de 43 Framework Atlas Servicios de Firma AFC Cliente String urlError 5.3. Url a la que redirigir al final de la firma si se ha producido algún error FIRMA DOCUMENTOS CADES Para realizar la firma del tipo Cades, exiten igualmente 2 métodos, firma individual: AfcOpClienteService /** * Solicita a AFC una operación de firma individual. * @param data contenido del documento a firmar * @param signInfo información de acceso a AFC. * @param loginCert certificado de login de usuario * @param opcionesPresentacion tipo de presentación del documento en AFC * @param urlOk url de retorno a la aplicación en una operación de firma correcta. * @param urlError url de retorno a la aplicación en una operación de firma incorrecta. * @return identificador de la operación en AFC (para recoger las firmas). * @throws ServiceException si hubo problemas */ <E extends Serializable> String solicitarFirmaIndividual(byte[] data, SignInfo<E> signInfo, X509Certificate loginCert, String opcionesPresentacion, String urlOk, String urlError) throws ServiceException; Y el método para firmas masivas: AfcOpClienteService /** * Solicita a AFC una operación de firma masiva CAdES * @param files ficheros a firmar * @param loginCertificate certificado de acceso para filtrado en selección * @param urlOk url de retorno a la aplicación en una operación correcta. * @param urlError url de retorno a la aplicación en una operación incorrecta. * @return url de acceso a la aplicación de firma al que redirigir al usuario * @throws ServiceException si hubo problemas */ <E extends Serializable> String solicitarFirmaCadesMasiva(Map<SignInfo<E>, byte[]> files, X509Certificate loginCertificate, String opcionesPresentacion, String urlOk, String urlError) throws ServiceException; Parámetro Map <SignInfo<E>, byte[]> Descripción Mapa con los ficheros a firmar y la información de AFC necesaria para realizar la firma 15 de 43 Framework Atlas Servicios de Firma AFC Cliente X509Certificate loginCert Certificado con el que se ha logado en la aplicación. Si no hay certificado se pone null. String opcionesPresentacion Opción de presentación: 1.- Se muestra el contenido del documento embebido en la página de la firma 2.- Se muestra una lista con el fichero a firmar y la posibilidad de pinchar en un enlace para visualizar el documento 3.- Modo ventana flotante 4.- Modo ventana flotante directa String urlOk Url a la que redirigir al final de la firma si todo a ido bien String urlError Url a la que redirigir al final de la firma si se ha producido algún error 6. PASOS PARA REALIZAR FIRMAS A continuación se muestra los pasos a seguir para realizar una firma 6.1.1. Preparación objetos Distinguimos entre llamadas a firmas individuales y firmas masivas. Firmas individuales Para realizar firmas individuales, independientemente del tipo de firma (pades, xades o cades), tan solo necesitamos configurar el objeto SignInfo<E>. Este objeto es del tipo que deseemos, el tipo escogido será utilizado como ID y en la mayoría de los casos de firma individual, bastará con usar la Clase String. El objeto SignInfo, requiere que se establezcan las siguientes propiedades: Atributo Descripción <E> providerId Objeto identificador de SignInfo. Puede ser del tipo que se desee String documentoTipo Atributo donde especificaremos el tipo de documento de AFC que queramos usar para la firma. Al dar de alta el acceso en AFC, podremos asociar a nuestro modulo a varios tipos de documentos. String numeroFirma Este atributo hace referencia al firmante para el tipo de documento de AFC, posee entre otras cosas la posición de la firma, si es visible o no, etc CoveInfo coveInfo Objeto Cove si se desea utilizar este servicio 16 de 43 Framework Atlas Servicios de Firma AFC Cliente String titulo Titulo del fichero a firmar Firmas masivas Para realizar firmas masivas de documentos es necesario distinguir entre los formatos PADES y CADES/XADES. o Firmas PADES masivas/hash Las firmas PADES masivas se basan en recoger el Hash de los documentos a firmar, firmarlo y volver a insertar dicho hash firmado en el documento pdf. Para ello, necesitaremos crear una clase que implemente la interfaz PdfFileProvider<T extends Serializable>, dicha interfaz obliga a nuestra clase a implementar los siguientes métodos: Void setSignedFile(T paramT, InputStream paramInputStream) InputStream getFileToSign(T paramT) T[] getFileIds() URI getDownloadUri(T paramT) SignInfo<T> getSignInfo(T paramT) CoveInfo getCoveInfo(T paramT) PdfSignatureAppearanceGenerator getPdfAppearance(T paramT) Donde <T> es la clase escogida como identificador. Se pueden ver ejemplos en las aplicaciones de ejemplo de atlas y FW2 y en este documento en el apartado Ejemplo Implementación PDF HASH o Firmas CADES/XADES masivas Las firmas Xades y Cades de forma masiva son iguales que las individuales, solo que usaremos un objeto Mapa para guardar los objeto SignInfo junto con los ficheros (byte[]). 6.1.1. Llamada a AFC Una vez creados los objetos necesarios, ejecutaremos la llamada al método y como resultado obtendremos una URL preparada con un parámetro token. Este token también se entrega adjunto en las URLs de retorno (Ok y Error) de forma que sea sencillo capturarlo para después hacer la petición del fichero firmado. 17 de 43 Framework Atlas Servicios de Firma AFC Cliente Llamada a servicio web de AFC para obtener URL (FirmaPdfIndividualAfcBean.java) // Envía la solicitud de firma a AFC String url = afcService.solicitarFirmaIndividual(pdf, signInfo, loginCert, operacionPresentacion, urlOk, urlError); 6.1.2. Realizar llamada a AFC Una vez obtenida el String con la URL que debemos utilizar para realizar la llamada a AFC, disponemos de 2 opciones. 1. Redirigir la llamada a la pantalla de AFC (Esto aplica para opciones de presentación 1 y 2) Redirigir llamada a AFC (FirmaPdfIndividualAfcBean.java) // Envía la solicitud de firma a AFC String url = afcService.solicitarFirmaIndividual(pdf, signInfo, loginCert, operacionPresentacion, urlOk, urlError); redirectToAfc(url); return null; 2. Establecer parámetro a true para mostrar IFrame (opciones de presentación 3 y 4) Redirigir llamada a AFC (FirmaPdfIndividualAfcPrBean.java) mostrarPanelFlotante =true; this.signUrl = afcUrl; 6.1.3. Opción de presentación con iFrame En caso de opción de presentación 3 no debemos redirigir a otra pantalla con la URL obtenida, sino que tendremos que actualizar el componente de iFrame incrustado en nuestra pantalla. De inicio, dispondremos de un elemento iFrame y una división lógica (div) que estarán inactivos, ambos componentes se refrescarán una vez obtenidos los datos de AFC. Necesitaremos 2 elementos importantes: firmaClienteIndividualFlotante.xhtml 18 de 43 Framework Atlas Servicios de Firma AFC Cliente <style> #fondoDesactivado { display: block; position: absolute; top:0; left:180px; width: 85%; height: 100%; background-color: white; opacity: .50; -webkit-opacity: .5; -moz-opacity: .5; filter: alpha(opacity=50); z-index: 1000; } #ventanaFlotante { background-color: white; border-radius: 10px; -webkit-border-radius: 10px; -moz-border-radius: 10px; box-shadow: 0 0 20px 0 #222; -webkit-box-shadow: 0 0 20px 0 #222; -moz-box-shadow: 0 0 20px 0 #222; display: block; top: 50; width: 400px; left: 50%; margin: -120px 0 0 -160px; padding: 10px; position: fixed; top: 50%; z-index: 1000; } </style> <div id="fondoDesactivado"></div> El panel transparente para evitar acciones en la pantalla origen firmaClienteIndividualFlotante.xhtml <h:panelGroup id="panelFlot”> <rich:panel rendered="#{firmaPdfIndividualAfcPrBean.mostrarPanelFlotante}"> … … … </rich:panel> </h:panelGroup> Ambos componentes está rodeados por un panel que será el que se refrescará una vez obtenida la URL del servicio de AFC: La variable mostrarPanelFlotante se establece por defecto a false: 19 de 43 Framework Atlas Servicios de Firma AFC Cliente FirmaPdfIndividualAfcPrBean.java /** * boolean que se encarga de mostrar/ocultar panel flotante */ private boolean mostrarPanelFlotante = false; Y se marca a true en cuanto disponemos de la URL de AFC FirmaPdfIndividualAfcPrBean.java if (opcionesPresentacion.equals("3")) { mostrarPanelFlotante =true; this.signUrl = url; } else { … } Establecemos el valor de “signUrl” con el valor obtenido del servicio de AFC. firmaClienteIndividualFlotante.xhtml <iframe src="#{firmaPdfIndividualAfcPrBean.signUrl}" El componente obtiene así la url de llamada del iFrame (por defecto es vacía). firmaClienteIndividualFlotante.xhtml <a4j:commandLink id="btnFirmaFlot" styleClass="botonAplicacionTXT" action ="#{firmaPdfIndividualAfcPrBean.procesarFirma}" render="panelFlot"> Para finalizar, solo debemos refrescar los componentes para que tanto el iFrame como el fondo bloqueante estén activos, para ello, en el botón que utilicemos para realizar la firma, hacer uso del atributo render. Donde panelFlot será el identificador del componente a refrescar. 20 de 43 Framework Atlas Servicios de Firma AFC Cliente 7. OPCIONES DE PRESENTACIÓN Existen tres opciones de presentación: 1. Se muestra el contenido del documento embebido en la página de firma 2. Se muestra una lista con el fichero a firmar y la posibilidad de pinchar en un enlace para visualizar el documento 21 de 43 Framework Atlas Servicios de Firma AFC Cliente 3. Se muestra un iFrame en la misma pantalla que realiza la llamada a AFC 4. Se muestra un iFrame en la misma pantalla que realiza la llamada a AFC y el usuario no tiene que confirmar la firma 22 de 43 Framework Atlas Servicios de Firma AFC Cliente 7.1.1. Recibir la respuesta de la firma. En el retorno se comprobará si ha habido errores y se recogerá el documento firmado (si no ha habido problemas). En JSF no existe ninguna forma de ejecutar una acción a partír de una URL externa, siempre se direccionarán páginas. Para redirigir la respuesta a un método de un ManagedBean y poder recoger el fichero firmado se utiliza la siguiente sección de código: firmaPdfIndividualDesdeAfc.xhtml <ui:composition template=”/WEB-INF/layout/vc.xhtml”> <f:metadata> <f:viewParam name=”error” required=”false” value=”#{firmaPdfIndividualResultadoAfcBean.error}” /> <f:viewParam name=”token” required=”true” value=”#{firmaPdfIndividualResultadoAfcBean.token}” /> <f:event type=”preRenderView” listener=”#{firmaPdfIndividualResultadoAfcBean.procesar}” /> </f:metadata> </ui:composition> De esta forma se recogen los parámetros error y token y se redirige la ejecución a un método del ManagedBean del resultado, en nuestro ejemplo firmaPdfIndividualResultadoAfcBean. Para evitar problemas en la recarga de la página, la redirección a la acción de un ManagedBean debe ser el único elemento en la página. 23 de 43 Framework Atlas Servicios de Firma AFC Cliente En el managedbean una vez recuperados los errores o las firmas se debe realizar una navegación forzada a la página de resultados: FirmaPdfIndividualResultadoAfcBean.java /** * Método que recoge la firma o los errores en caso de error * y redirecciona a la página de recogida de firma */ public void procesar() { try { // comprobar si ha habido errores boolean bError = error ¡= null && “true”.equalsIgnoreCase(this.error); if (bError) { log.info(“Respuesta de ERROR recibida de AFC.”); AtlasFacesUtils.addErrorMessage(“Error en la firma”); Map<UUID, String> listaErrores = this.afcService.recogerErrores(token); // Encola todos los errores de AFC como error messages de jsf for (UUID uuid : listaErrores.keySet()) { AtlasFacesUtils.addErrorMessage(listaErrores.get(uuid)); } } else { log.info(“Respuesta CORRECTA recibida de AFC.”); byte[] pdf = this.afcService.recogerFirma(this.token); // Preparar ficheros para descarga this.name = (String) AtlasFacesUtils.loadFromSession(PARAM_FILE_NAME, true); this.fileId = (URL) AtlasFacesUtils.loadFromSession(PARAM_FILE_PATH, true); // Guardar contenido de fichero firmado en disco this.outputPath = setSignedFile(name, new ByteArrayInputStream(pdf)); } // Redirigir a la pagina de descarga del fichero log.info(“Redireccionando a página “ + VISTA_RESULTADO); AtlasFacesUtils.navigateTo(VISTA_RESULTADO); } catch (ServiceException e) { log.error(“Error procesando firmas en AFC”, e); AtlasFacesUtils.addErrorMessage(“Error procesando firmas en AFC”); } } 24 de 43 Framework Atlas Servicios de Firma AFC Cliente 7.1.2. Recepción de respuesta con anotación @PostConstruct La otra manera de implementar la recepción de la respuesta es utilizando la anotación @PostConstruct en el bean de respuesta. Para implementar esta solución hay que implementar los siguientes pasos: 1. Página firmaPdfIndividual.xhtml: página que se encargará de seleccionar el fichero a firmar. 2. Managed bean FirmaPdIndividualAfcBean.java desde este managed bean se inicia el proceso de firma solicitando la url de firma al Servicio de AFC y redirigiendo al usuario a afc_firmacliente 3. Managed bean FirmaPdfIndividualResultadoAfcBean.java: Esta managedbean se encargará de gestionar el resultado de afc_firmacliente (ok o error) y obtener el fichero firmado o los errores en el caso de que haya habido algún error. 4. Página firmaPdfIndividualResultado.xhtml: página que muestra el resultado de la firma una vez recuperado. Esta modalidad se desarrolla igual que la anteriormente descrita con la salvedad de que no es necesario establecer una página de recarga previa a la recepción en la página de resultado. Lo único que hay que tener en cuenta es la necesidad de anotar el método procesar como @PostConstruct lo que indica que este método debe ser llamado una vez ejecutado el constructor del bean pero antes de realizar nada más, con lo que tendremos las propiedades correctamente inyectadas. 25 de 43 Framework Atlas Servicios de Firma AFC Cliente La implementación del managed bean para la página de resultado sería así: FirmaPdfIndividualResultadoAfcBean.java /** * Método que recoge la firma o los errores en caso de error * y redirecciona a la página de recogida de firma */ @PostConstruct public void procesar() { if (!FacesContext.getCurrentInstance().isPostback()) { try { this.token = FacesContext.getCurrentInstance().getExternalContext(). getRequestParameterMap().get("token"); this.error = FacesContext.getCurrentInstance().getExternalContext(). getRequestParameterMap().get("error"); // comprobar si ha habido errores boolean bError = error ¡= null && “true”.equalsIgnoreCase(this.error); if (bError) { log.info(“Respuesta de ERROR recibida de AFC.”); AtlasFacesUtils.addErrorMessage(“Error en la firma”); Map<UUID, String> listaErrores = this.afcService.recogerErrores(token); // Encola todos los errores de AFC como error messages de jsf for (UUID uuid : listaErrores.keySet()) { AtlasFacesUtils.addErrorMessage(listaErrores.get(uuid)); } } else { log.info(“Respuesta CORRECTA recibida de AFC.”); byte[] pdf = this.afcService.recogerFirma(this.token); // Preparar ficheros para descarga this.name = (String) AtlasFacesUtils.loadFromSession(PARAM_FILE_NAME, true); this.fileId = (URL) AtlasFacesUtils.loadFromSession(PARAM_FILE_PATH, true); // Guardar contenido de fichero firmado en disco this.outputPath = setSignedFile(name, new ByteArrayInputStream(pdf)); } // Redirigir a la pagina de descarga del fichero log.info(“Redireccionando a página “ + VISTA_RESULTADO); AtlasFacesUtils.navigateTo(VISTA_RESULTADO); } catch (ServiceException e) { log.error(“Error procesando firmas en AFC”, e); AtlasFacesUtils.addErrorMessage(“Error procesando firmas en AFC”); } } } ATENCION Si se opta por implementar @PostConstruct es muy importante que el archivo web.xml de la aplicación NO tenga el atributo metadata-complete, de la etiqueta <web-app> con valor true ya que esto puede dar problemas a la hora de interpretar la anotación en algunos servidores de aplicaciones. 26 de 43 Framework Atlas Servicios de Firma AFC Cliente 8. EJEMPLO IMPLEMENTACIÓN PDF HASH La firma masiva de documentos PDF se realiza contra los ficheros hash de los pdfs, de esta forma se evita que los ficheros tengan que viajar a la aplicación de firma y que el rendimiento de la firma sea mejor ya que el tamaño del hash es el mismo independientemente del tamaño del fichero a firmar. La generación de los hash se hace en la aplicación cliente por lo tanto en el caso de firma masiva antes de llamar a AFC hay que hacer una serie de operaciones. Los pasos para la realización de una firma masiva son: 5. Creación de una clase que implemente el interfaz PdfFileProvider 6. Página firmaPdfMasiva.xhtml: página que se encargará de seleccionar el certificado de firma. 7. Solicitud de la firma en FirmaPdMasivaAfcBean.java esta acción se encargará de preparar los hash de los ficheros y solicitar la operación de firma a AFC y redirigir al usuario a AFC_Cliente. 8. Página firmaPdfMasivaDesdeAfc.xhtml: en el retorno del usuario desde AFC esta página redirigirá el control de ejecución al bean FirmaPdfMasivaResultadoAfcBean. 9. Acción FirmaPdfMasivaResultadoAfcBean.java: esta acción se encargará de gestionar el retorno desde AFC e incrustar las firmas en los PDF. 10. Página firmaPdfMasivaResultado.xhtml: página que muestra el resultado de la firma y permite descargar tanto los ficheros originales como los firmados 27 de 43 Framework Atlas Servicios de Firma AFC Cliente 8.1.1. Implementación de la Interfaz PdfFileProvider Cuando se quiere realizar una firma masiva de documentos Pdf en cliente, será necesario implementar esta interfaz. Dicha interfaz es una extensión de otra interfaz base llamada FileProvider. Esta implementación se encargará de interactuar con los servicios de firma para proporcionar la información necesaria y recoger los ficheros firmados. En los ejemplos de la aplicación atlas_integracion_asf, el tipo del identificador en que se basa la interfaz es una URL. Este objeto es el más conveniente si los ficheros residen en disco. Para ficheros en base de datos se pueden utilizar objetos Long o String que identifiquen la clave primaria de este. Otra opción es construir un bean de datos con la información necesaria para identificar el fichero en el sistema donde este resida, y establecer su tipo como Id de la interfaz. La única restricción es que este objeto ha de ser Serializable. Una vez establecido el tipo del identificador del fichero, la implementación de PdfFileProvider planteará pocos problemas. FileProvider public interface FileProvider<T extends Serializable> { /** * Devuelve una lista de identificadores que serán iterados para obtener * los ficheros a firmar. * @return */ T[] getFileIds() throws ServiceException; /** * Devuelve un objeto InputStream del fichero a firmar. El fichero será * elegido en base al identificador pasado * @param fileId * @return */ InputStream getFileToSign(T fileId) throws ServiceException; /** * A este metodo se entrega el objeto InputStream del fichero ya firmado * junto con su identificador para que sea almacenado. * @param fileId * @param signed */ void setSignedFile(T fileId, InputStream signed) throws ServiceException; 28 de 43 Framework Atlas Servicios de Firma AFC Cliente La interfaz PdfFileProvider permite además configurar la apariencia de la firma PDF (solo en casos estrictamente necesarios) y aportar información para la inserción del código COVE. PdfFileProvider public interface PdfFileProvider<T extends Serializable> extends FileProvider<T> { /** * Metodo para personalizar la apariencia de la firma de pdf. Si se devuelve * null, la apariencia será la estándar. * @param fileId identificador del fichero * @return objeto que renderizará la apariencia de la firma pdf * @throws ServiceException */ PdfSignatureAppearanceGenerator getPdfAppearance(T fileId) throws ServiceException; /** * Retorna un objeto con información necesaria para obtener el código * COVE e insertarlo en el documento * @param fileId identificador del fichero sobre el que se está pidiendo * la información COVE. * @return objeto de datos de COVE. */ CoveInfo getCoveInfo(T fileId); /** * Debe retornar un objeto {@link SignInfo} con la informacion de firma * relativa al fichero con el identificador pasado * @param fileId identificador del fichero a firmar * @return devuelve la configuarción de AFC para este fichero. */ SignInfo<T> getSignInfo(T fileId); /** * Retorna la URI de visualización del fichero cuando se selecciona la * operacion en AFC. La implementación de esta interfaz deberá * proporcionar una URI donde se pueda descargar el fichero con el * id indicado. * @param fileId * @return */ URI getDownloadUri(T fileId); } 29 de 43 Framework Atlas Servicios de Firma AFC Cliente La forma de uso de esta interfaz será la siguiente: 1. En un primer estado se llamará al método getFileIds() y la implementación de esta interfaz tendrá que retornar una lista de identificadores únicos, uno por cada fichero que se quiera firmar. 2. Por cada uno de los identificadores entregados en el paso anterior se solicitará el contenido a firmar llamando al método getFileToSign(id) . La implementación deberá retornar un objeto InputStream apuntando al contenido del fichero. Se realizarán tantas llamadas a getFileToSign como identificadores se entreguen en el paso 1. 3. Una vez concluido el proceso de firma masiva, el sistema realizará llamadas a setSignedFile() para entregar a la implementación los ficheros firmados. Se realizarán tantas llamadas como identificadores se entreguen en el paso 1. La interfaz FileProvider está parametrizada según el tipo de identificadores pasados. El tipo concreto de la interfaz lo decidirá la implementación aportando los Ids de los ficheros a firmar. El único requisito sobre el tipo del identificador es que este sea Serializable. Este puede ser un bean con atributos que identifiquen el fichero en el sistema destino, o un único código. En los ejemplos del capítulo siguiente, dado que los ficheros de prueba residen en el sistema, se ha establecido el identificador de fichero como un objeto de tipo URL que apuntará a la ubicación de este en el disco. En cuanto a la apariencia de la firma pdf, las posibilidades son las siguientes: 1. Si la apariencia es igual en todos los ficheros (tipos de letra, coordenadas, etc), la implementación más simple es la siguiente: 2. Las configuraciones de apariencia de firma son distintas para cada fichero (distinta configuración de fuente o de coordenadas). 30 de 43 Framework Atlas Servicios de Firma AFC Cliente Si la apariencia es igual en todos los ficheros (tipos de letra, coordenadas, etc), la implementación más simple es la siguiente: Implementación de PdfFileProvider /** * Apariencia personalizada. No se establece por defecto. El controlador lo hara */ PdfSignatureAppearanceGenerator appearance = null; /** * Obtiene la apariencia de la firma previamente almacenada. * Solo para ficheros PDF. */ @Override public PdfSignatureAppearanceGenerator getPdfAppearance(URL fileId) { return this.appearance; } /** * Establece la apariencia de la firma de los documentos PDF. * El uso normal es almacenar aqui * una versión de apariencia acorde a los metadatos de la firma * obtenidos de AFC_Cliente. * @param appearance implementación de apariencia de firma en documentos pdf. */ public void setAppearance(PdfSignatureAppearanceGenerator appearance) { this.appearance = appearance; } dejando la responsabilidad de establecer la apariencia a la clase que instancia este proveedor de ficheros pdf (se verá en detalle en los ejemplos de firma masiva). 31 de 43 Framework Atlas Servicios de Firma AFC Cliente Si las configuraciones de apariencia de firma son distintas para cada fichero (distinta configuración de fuente o de coordenadas). Este es el caso más general. Lo primero que habrá que hacer es obtener los metadatos de cada fichero y preparar el método getPdfAppareace para devolver un objeto PdfSignatureAppearanceGenerator creado a partir de los metadatos. Implementación de PdfFileProvider DemoPdfProvider.java /** * Obtiene los metadatos de todos los ficheros a firmar * Estos están definidos en AFC_GEST / Tipos de documento y Formatos de Firma * * @param afcService librería de operaciones en cliente de AFC * @throws ServiceException */ public void obtenerMetadatosFirma(AfcOpClienteService afcService) throws ServiceException { // Obtener los ids de los ficheros a firmar if (this.fileIds == null) { getFileIds(); } // Recopilar los metadatos de firma para cada fichero for (URL fileId : this.fileIds) { // Preparar informacion de firmado para el fichero SignInfo<URL> signInfo = new SignInfo<URL>(); this.signInfos.put(fileId, signInfo); // Almacenar informacion de acceso a AFC signInfo.setProviderId(fileId); signInfo.setDocumentoTipo(getAfcTipoFirma(fileId)); signInfo.setNumeroFirma(getAfcNumeroFirma(fileId)); signInfo.setTitulo(getName(fileId)); } // Pedir todos los metadatos a AFC en una sola llamada // Rellena el campo metadatosFirma de cada signInfo afcService.getMetadatosFirma(this.signInfos.values() .toArray(new SignInfo[0])); } /** * Devuelve la apariencia de la firma PDF configurada segun los metadatos en AFC */ @Override public PdfSignatureAppearanceGenerator getPdfAppearance(URL id) { SignInfo signInfo = this.signInfos.get(id); if (signInfo == null) { throw new ServiceException("El Id pasado no existe."); } return PdfSignatureAppearanceAfc.getPdfAppearance( signInfo.getMetadatosFirma()); } 32 de 43 Framework Atlas Servicios de Firma AFC Cliente Esta implementación depende de una estructura de datos de objetos SignInfo. Este objeto es una utilidad para recoger los datos necesarios para la firma: SignInfo.java public class SignInfo<E extends Serializable> implements Serializable, Cloneable { /** Identificador único del elemento a firmar */ private E providerId; /** Código de tipo de firma. Parametrizado en AFC_GEST */ private String documentoTipo; /** Código de numero de firma */ private String numeroFirma = "1"; // valor por defecto /** Informacion para generar COVE */ private CoveInfo coveInfo; /** Titulo del documento a mostrar en la pantalla de firma de AFC */ private String titulo; /** Identificador del fichero para la descarga */ private UUID uuid; /** Metadatos de la firma en AFC - Definidos en AFC_GEST */ private ResultadoSolicitarDatosFirma metadatosFirma; ... Todos estos parámetros son obligatorios. Las implementaciones de esta interfaz se verán en más detalle en los ejemplos de código. 8.1.2. Selección del certificado cliente para la firma En la firma masiva la selección del certificado se ha de hacer en la aplicación cliente ya que para poder preparar los pdfs para la firma y hacer los hash es necesario tener previamente el certificado digital con el que se va a firmar. El componente de selección de certificados usado está en la librería atlasfrm-componentes-lib. Se puede ver un ejemplo de uso en la aplicación de ejemplo atlas_integracion_asf: src/main/webapp/secure/afc/firmaDigital/cliente/firmaPdfMasiva.xhtml 33 de 43 Framework Atlas Servicios de Firma AFC Cliente <html xmlns="http://www.w3.org/1999/xhtml" ... xmlns:atlasafccrypt="http://atlas.core.componentes/jsf/atlasafccrypt"> <head <atlasafccrypt:head /> </head> . . <atlasafccrypt:certificados debug="true" assignTo="#{firmaPdfMasivaAfcBean.certificado}" /> Para la carga del certificado, el applet <atlasafccrypt:certificados cargará 2 ficheros .js, a partir de la versión 1.2.8 de atlas no será necesario ninguna configuración, en versiones anteriores será necesario disponer de las siguientes variables en nuestro enviroment.properties : environment.properties afc.clientJSUrl=https://desarrollo3.madrid.org/afirma/firma afc.clientMiniJsUrl=https://desarrollo3.madrid.org/afirma/mini Donde desarrollo3 correspondería con el entorno. Además de la configuración siguiente en el fichero de configuración de afc de Spring: applicationContext-services-afc.xml <bean id="atlasAfcConfiguration" class="atlas.componentes.afccrypt.AtlasAfcConfiguration"> <property name="clientJSUrl" value="${afc.clientJSUrl}" /> <property name="clientMiniJSUrl" value="${afc.clientMiniJsUrl}" /> </bean> NOTA: la configuración arriba indicada NO debe existir para proyectos atlas iguales o superiores a 1.2.8 Los atributos disponibles de este componente son: Atributo Obligatorio Valor por defecto Descripción 34 de 43 Framework Atlas Servicios de Firma AFC Cliente filtrarCAs NO true Si el valor es true, se filtrarán los certificados listados en el combo según la configuración en la plataforma ASF en la operación de VERIFICACION. Si el valor es una expresión de JSF que apunta a una variable de un ManagedBean, se tomará el certificado almacenado en el Bean como referencia de filtrado en lugar del certificado de login. El certificado debe estar cifrado en Base64. assignTo NO -- Si el valor es una expresión JSF que apunta a un atributo de un ManagedBean, cada vez que el usuario seleccione un certificado, este se enviará al servidor y se guardará en el atributo configurado. cargarCerts NO true Si el valor es true se cargarán los certificados; en caso contrario se cargará el applet de firma, pero no los certificados. debug NO false Si el valor es true se mostrará un panel de log. El atributo debug solo se podrá utilizar mientras se desarrolla y prueba la página notify NO -- En este parámetro se puede indicar el nombre de una función javascript a la que se llamará cada vez que se seleccione un certificado. forzarCert NO -- Si el valor es una expresión JSF que apunta a una variable de un ManagedBean, solo se mostrará el certificado de la variable en la selección (el certificado forzado debe estar en el almacén de certificados del usuario). 35 de 43 Framework Atlas Servicios de Firma AFC Cliente 8.1.3. Selección del certificado cliente para la firma En el método procesarFirma de FirmaPdfMasivaAfcBean es donde se generan los hash de los ficheros pdf (se hace en local) y se envian a firma a AFC procesarFirma() en FirmaPdfMasivaAfcBean.java @ManagedProperty(value="#{afcOpClienteService}") private AfcOpClienteService afcService; @ManagedProperty(value="#{fileProvider}") private DemoPdfFileProvider fileProvider; public String procesarFirma() { … // Obtener metadatos de firma para todos los tipos de firma log.info("Solicitando metadatos de firma..."); fileProvider.obtenerMetadatosFirma(this.afcService); // Obtener el certificado con el que firmar X509Certificate cert = CertificateUtil.getCertificateFromString(this.certificado); // Configurar URLs de retorno String urlOk = DescargaPdf.getBaseUrl() + VISTA_RESULTADO; String urlError = urlOk + "?error=true"; // Crea los hash de los pdf prepara la firma de los mismos String afcUrl = afcService.solicitarFirmaPdfMasiva(fileProvider, opcionesPresentacion cert, urlOk, urlError); // Guardar provider en sesión para el retorno de AFC AtlasFacesUtils.storeOnSession(PARAM_FILE_PROVIDER, this.fileProvider); … } Antes de realizar la llamada a afcService.solicitarFirmaPdfMasiva será necesario implementar el objeto fileProvider y recuperar el certificado desde la página como se ha descrito anteriormente. En caso de la llamada a AFC el procedimiento es el mismo que con la firma individual, dependiendo de la opción de presentación escogida, se redirigirá o se mostrara un componente iFrame. 36 de 43 Framework Atlas Servicios de Firma AFC Cliente 8.1.4. Recibir la respuesta de las firmas. En el retorno se comprobará si ha habido errores y se recogerá el documento firmado (si no ha habido problemas). En JSF no existe ninguna forma de ejecutar una acción a partír de una URL externa, siempre se direccionarán páginas. Para redirigir la respuesta a un método de un ManagedBean y poder recoger el fichero firmado se utiliza la siguiente sección de código: firmaPdfIndividualDesdeAfc.xhtml <ui:composition template=”/WEB-INF/layout/vc.xhtml”> <f:metadata> <f:viewParam name=”error” required=”false” value=”#{firmaPdfMasivaResultadoAfcBean.error}” /> <f:viewParam name=”token” required=”true” value=”#{firmaPdfMasivaResultadoAfcBean.token}” /> <f:event type=”preRenderView” listener=”#{firmaPdfMasivaResultadoAfcBean.procesar}” /> </f:metadata> </ui:composition> 8.1.5. Recogida de firmas y procesado de las mismas La gestión de los resultados se realiza en la clase FirmaPdfMasivaResultadoAfcBean: Gestión resultado firma (FirmaPdfMasivaResultadoAfcBean.java) 37 de 43 Framework Atlas Servicios de Firma AFC Cliente public void procesar() { try { // Recuperar el provider de la sesión this.fileProvider = (DemoPdfFileProvider) AtlasFacesUtils.loadFromSession(PARAM_FILE_PROVIDER, true); // Comprobar si ha habido errores boolean bError = error != null && "true".equalsIgnoreCase(this.error); if (bError) { log.info("Respuesta de ERROR recibida de AFC."); AtlasFacesUtils.addErrorMessage("Error en la firma"); Map<UUID, String> listaErrores = this.afcService.recogerErrores(token); // Encola todos los errores de AFC como error messages de jsf for (UUID uuid : listaErrores.keySet()) { String outPath = fileProvider.outputFiles .get(this.providerIds.get(uuid)); String name = DemoPdfFileProvider.getName(outPath); AtlasFacesUtils.addErrorMessage(name + ": " + listaErrores.get(uuid)); } } else { log.info("Respuesta CORRECTA recibida de AFC."); // Recupera las firmas de AFC y las inserta en los ficheros PDF // se entregarán a la implementación de PdfFileProvider this.providerIds = this.afcService.procesarFirmas( this.fileProvider, token); // Preparar ficheros para descarga this.firmas = new ArrayList<DescargaBean>(); for (UUID id : this.providerIds.keySet()) { String outPath = fileProvider.outputFiles.get(this.providerIds.get(id)); String name = DemoPdfFileProvider.getName(outPath); firmas.add(new DescargaBean(id.toString(), name)); } // Ordenar la lista por el nombre del fichero Collections.sort(firmas, new ComparatorByName()); } // Redirigir a la pagina de descarga de los ficheros log.info("Redireccionando a página " + VISTA_RESULTADO); AtlasFacesUtils.navigateTo(VISTA_RESULTADO); } catch (ServiceException e) { log.error("Error procesando firmas en AFC", e); AtlasFacesUtils.addErrorMessage("Error procesando firmas en AFC"); } } Para obtener información ampliada, consultar la aplicación de ejemplo. 9. EJEMPLO CADES/XADES 38 de 43 Framework Atlas Servicios de Firma AFC Cliente 9.1. FIRMA INDIVIDUAL DOCUMENTOS XML El procedimiento para ejecutar una firma XAdES es similar al de firma individual de Pdf. Los pasos a seguir son los mismos y solo hay pequeñas variaciones como el nombre de los métodos a llamar y la configuración de la firma. En el caso de la firma xades individual, tanto firma normal, cofirma o contrafirma, no será obligatorio solicitar los metadatos de la firma, por lo que las interacciones con AFC quedan reducidas a dos: solicitud de firma y recogida del fichero firmado. Solicitud de firma XAdES (FirmaXadesIndividualAfcBean.java) private String xml; private String visualizacion; ... // Obtener el certificado de login para filtrado en pagina de firma X509Certificate loginCert = UserUtil.getUserCertificate(); // Configurar URLs de retorno String urlOk = DescargaUtil.getBaseUrl() String urlError = urlOk + "?error=true"; + VISTA_AFC_RESULTADO; String afcUrl = afcService.solicitarFirmaIndividual(xml.getBytes(), getSignInfoFirma(), loginCert, opcionesPresentacion urlOk, urlError); if (this.visualizacion.equals("3")) { this.signUrl = afcUrl; mostrarPanelFlotante =true; } else { AtlasFacesUtils.redirectTo(afcUrl); } La única diferencia entre firmas, cofirmas y contrafirmas Xades es el tipo de documento pasado en el objeto SignInfo. En la aplicación de ejemplo, una vez realizara una firma XAdES se activan las opciones de cofirma y contrafirma (solo son útiles con ficheros ya firmados). 39 de 43 Framework Atlas Servicios de Firma AFC Cliente 9.2. FIRMA MASIVA DOCUMENTOS XML El caso de la firma XAdES masiva es más sencillo que la firma de Pdf y no necesita de una implementación de interfaz para intercambio de datos. A continuación se muestra un ejemplo de código: Solicitar firma XAdES (FirmaXadesMasivaAfcBean.java) // Obtener el certificado de login para filtrado en pagina de firma X509Certificate loginCert = UserUtil.getUserCertificate(); Map<URL, byte[]> xmls = getXmlFiles();// Ficheros XML de demostracion // Estructrura de objetos SignInfo (info de firma) y contenidos de los XML Map<SignInfo<URL>, byte[]> datos = new HashMap<SignInfo<URL>, byte[]>(); for (URL url : xmls.keySet()) { datos.put(getSignInfo(url), IOUtils.toByteArray(url)); } // Configurar URLs de retorno String urlOk = DescargaUtil.getBaseUrl() String urlError = urlOk + "?error=true"; + VISTA_AFC_RESULTADO; // Configurar datos de firmado log.info("Realizando peticion de firma masiva...."); String afcUrl = this.afcService.solicitarFirmaXadesMasiva(datos, loginCert, opcionesPresentacion, urlOk, urlError); // Guardar nombre para guardar el resultado de la firma en AFC ... if (this.visualizacion.equals("3")) { this.signUrl = afcUrl; mostrarPanelFlotante =true; } else { AtlasFacesUtils.redirectTo(afcUrl); } Recogida de documentos firmados (FirmaXadesMasivaResultado.java) boolean bError = error != null && "true".equalsIgnoreCase(this.error); if (bError) { log.info("Respuesta de ERROR recibida de AFC."); AtlasFacesUtils.addErrorMessage("Se han producido errores en la firma."); Map<UUID, String> listaErrores = this.afcService.recogerErrores(token); ... } else { log.info("Respuesta CORRECTA recibida de AFC."); // Procesar firmas y almacenar ficheros en disco Map<UUID, String> firmas = this.afcService.recogerFirmas(token); ... 9.3. FIRMA INDIVIDUAL CADES 40 de 43 Framework Atlas Servicios de Firma AFC Cliente El procedimiento para ejecutar una firma CAdES es similar al de firma XAdES. Los pasos a seguir son los mismos y solo hay pequeñas variaciones como el nombre de los métodos a llamar y la configuración de la firma. En el caso de la firma cades individual, no será obligatorio solicitar los metadatos de la firma, por lo que las interacciones con AFC quedan reducidas a dos: solicitud de firma y recogida del fichero firmado. Solicitud de firma CAdES (FirmaCadesIndividualAfcBean.java) private byte[] data; private String visualizacion; ... // Obtener el certificado de login para filtrado en pagina de firma X509Certificate loginCert = UserUtil.getUserCertificate(); // Configurar URLs de retorno String urlOk = DescargaUtil.getBaseUrl() String urlError = urlOk + "?error=true"; + VISTA_AFC_RESULTADO; String afcUrl = afcService.solicitarFirmaIndividual(data, getSignInfoFirma(), loginCert, opcionesPresentacion, urlOk, urlError); log.info("Enviando usuario a AFC: '" + afcUrl + "'."); AtlasFacesUtils.redirectTo(afcUrl); 41 de 43 Framework Atlas Servicios de Firma AFC Cliente 9.4. FIRMA MASIVA CADES El caso de la firma CAdES masiva es también muy similar a la firma XAdES masiva, y no necesita de una implementación de interfaz para intercambio de datos. A continuación se muestra un ejemplo de código: Solicitar firma CAdES (FirmaCadesMasivaAfcBean.java) // Obtener el certificado de login para filtrado en pagina de firma X509Certificate loginCert = UserUtil.getUserCertificate(); Map<URL, byte[]> ficheros = getDemoFiles();// Ficheros de demostracion // Estructrura de objetos SignInfo (info de firma) y contenidos de los ficheros Map<SignInfo<URL>, byte[]> datos = new HashMap<SignInfo<URL>, byte[]>(); for (URL url : ficheros.keySet()) { datos.put(getSignInfo(url), IOUtils.toByteArray(url)); } // Configurar URLs de retorno String urlOk = DescargaUtil.getBaseUrl() String urlError = urlOk + "?error=true"; + VISTA_AFC_RESULTADO; // Configurar datos de firmado log.info("Realizando peticion de firma masiva...."); String afcUrl = this.afcService.solicitarFirmaCadesMasiva(datos, loginCert,opcionesPresentacion, urlOk, urlError); // Guardar nombre para guardar el resultado de la firma en AFC ... log.info("Enviando usuario a AFC: '" + afcUrl + "'."); AtlasFacesUtils.redirectTo(afcUrl); Recogida de documentos firmados (FirmaCadesMasivaResultado.java) boolean bError = error != null && "true".equalsIgnoreCase(this.error); if (bError) { log.info("Respuesta de ERROR recibida de AFC."); AtlasFacesUtils.addErrorMessage("Se han producido errores en la firma."); Map<UUID, String> listaErrores = this.afcService.recogerErrores(token); ... } else { log.info("Respuesta CORRECTA recibida de AFC."); // Procesar firmas y almacenar ficheros en disco Map<UUID, String> firmas = this.afcService.recogerFirmas(token); ... 42 de 43 Framework Atlas Servicios de Firma AFC Cliente ENLACES RELACIONADOS Producto URL Axis2 http://ws.apache.org/axis2/ Certificados ICM http://desarrollo.madrid.org/certificados/ Descarga certificados de prueba http://desarrollo.madrid.org/certificados/descarga_de_certificados.htm 43 de 43