En este apartado se muestran dos casos de uso donde intervienen integraciones con MFE.
1.- MFE - Módulo de indentificación
1.1.- Ejemplo identificación 1: Identificación y acceso en una portal para empleados
Este es un ejemplo de integración de un portal para empleados de la administración pública. Utiliza el framework Struts2 y todos los datos y los organismos a los que pertenece el empleado se extraen del Sistema de Identificación de Usuarios (SIU)
El flujo de este portal es el siguiente: el empleado se identifica en la página de login. Una vez identificado, en la parte servidor, el portal valida el token de identificación y busca en SIU sus organismos asociados. Los muestra al empleado, éste selecciona con qué organismo desea trabajar y accede al sistema.
1.1.1.- Parte cliente
En la página de login se aplicarían los pasos indicados en el punto 4.- Integración con MFE.
<!--PÁGINA DE LOGIN DEL PORTAL --> <html> <head> (...) <!-- MFE: 1) etiqueta compatibilidad ie --> <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> <!-- MFE: 2) javascript --> <script type="text/javascript" src="http://integracion/mfe_core/js/sslssso.js"></script> </head> <script> <!-- MFE: 4) función donde se recoge el token jwt cuando el usario se ha identificado --> function onIdentification(operation) { console.log("[LOGIN] BEGIN onIdentification()"); document.getElementById("jwt").value = operation.jwt; document.getElementById('divIFrame').innerHTML = "Se estan cargando los organismos del usuario "; var arrayOrganism = <%=request.getAttribute("arrayOrganism")%>; if((arrayOrganism == null || arrayOrganism == 'undefined') && $("#tokenJWT").val() != "") { // Usuario identificado. Enviamos el formulario para validar token y obtener organismos document.getElementById("formulario").submit(); } console.log("[LOGIN] END onIdentification()"); } </script> <body> <s:form id="formulario" action="login_validateLogin"> <% Organism[] arrayOrganism = (Organism[]) request.getAttribute("arrayOrganism"); if (arrayOrganism !=null && arrayOrganism[0] != null) { %> <!-- Código htm para mostrar el combo de organismos --> (...) <% } else { %> <div align="center" id="divIFrame"> <!-- MFE: 3) iframe para los métodos de identificación --> <iframe id="mfe_iframe" src="http://integracion/mfe_core/rest/identification/SNT/ <%=new String(Base64.encodeBase64("http://integracion/snt_pf_v3/login_validateLogin.action").getBytes("UTF-8")),"UTF-8") %>"> </iframe> </div> <% } %> <s:hidden key="jwt" id="jwt" value=""/> </s:form> <body> </html>
-
1.1.2.- Parte servidor
Validación de identificación y obtención de organismos tras integración con MFE – Identificación
Una vez que en que se invoca a la función java script onIdentification , se debe invocar a la parte servidor enviando el token jwt obtenido de la identificación.
Una vez en la parte servidor, primero se debe validar el token jwt contra el servicio de MFE. En caso de que suceda algún error o la identificación no sea válida, antes de volver a la página de login se debe realizar un cierre de sesión mediante un logout con MFE.
En caso de que la identificación sea correcta se obtendrán los organismos de SIU.
-
/** * Método que valida la identificación de un empleado, obtiene los organismos * asociados de éste y vuelve a la página de inicio del portal para que * el empleado seleccione el organismo con el que trabajar * * @return vuelta a la página de inicio. */ public final String validateLogin() { // se obtiene el token jwt resultado de la identificación jwt = (String) request.getSession().getAttribute(JWTDATA); if (jwt) { return "ERROR_JSP"; } // Método que valida el token jwt contra MFE y devuelve el identificador de usuario. // En caso de error o token no válido devuelve nulo. String idUser = validateJwt(idApplicationMFE, jwt); if (idUser == null) { return logOut(); } arrayOrganism = getOrganisms(idUser); return "LOGIN_JSP"; }
En el ejemplo, para invocar al servicio rest de validación de MFE se utilizan las siguientes clases:
com.sun.jersey.api.client.Client
com.sun.jersey.api.client.WebResource
Las librerías utilizadas son:
Java 1.5: jersey-client-1.2.jar (dependiencias jersey-core-1.2.jar y jsr311-api-1.1.1.jar)
Java 1.7 : jersey-client-1.8.jar (dependiencias jersey-core-1.8.jar )
Para tratar la respuesta json del servicio se utilizan las siguientes clases de la librería json-simple1.1.jar
org.json.simple.JSONObject
org.json.simple.parser.JSONParser
org.json.simple.parser.ParseException
/** * Método que valida el jwt que genera la identificación y devuelve el identificador de usuario * @param applicationId, identificador de la aplicación en MFE * @param jwt, token jwt resultado de la identificación * @return el identificador de usuario. En caso de error devuelve nulo. * @throws ParseException */ private String validateJwt(String applicationId, String jwt) throws ParseException { // Generamos una llamada al servicio REST de MFE Client mfeClient = Client.create(); WebResource mfeResource = mfeClient.resource(NTPfConfig.getMfeUrl()).path("rest/identificationValidation").path(applicationId); mfeResource = mfeResource.queryParam("jwt", jwt); // Realizamos la invocación POST String jsonRaw = mfeResource.post(String.class); // Parseamos la respuesta del servicio REST a un objeto JSON JSONParser jsonParser = new JSONParser(); JSONObject json = (JSONObject) jsonParser.parse(jsonRaw); // Comprobamos el status del json String status = (String) json.get("status"); String idUser = null; if ("SUCCESS".equals(status)) { idUser = (String) json.get("eIdentifier"); String identificationMethod = (String) json.get("identificationMethod"); // Guardamos el método de identificación para utlilizarlo en el cierre de sesión. request.getSession().setAttribute("identificationMethod", identificationMethod); log.info("Validación de identificación en MFE correcta, usuario: + " + idUser + ", método de identificación: " + identificationMethod); } else if ("ERROR".equals(status)) { addActionMessage("Ha sucedido un error durante su identificación"); log.error("Validación de la identificación en MFE estado ERROR: " + json.get("errorMessage")); } else if ("NOT_VALID".equals(status)) { addActionMessage("Su idenficación no es válida. Por favor, vuelva a identificarse"); log.error("Validación de la identificación en MFE estado NOT_VALID: " + json.get("errorMessage")); } else {// NOT_VALID_SSO. No mostramos mensaje al usuario ya que debería ser transparente la nueva identificación. log.info("Validación de la identificación en MFE estado NOT_VALID_SSO: " + json.get("errorMessage")); } return idUser; }
Una vez validado el token jwt y obtenidos los datos del usuario, para obtener sus organismos invocamos al
servicio de SIU additionalDataOrganismListByUser en vez de a ancestralOrganismByUserList
/** * Método que obtiene el listado de organismos en SIU a partir de un identificador de * usuario * @param identificador de usuario * @return listado de organismos asociados al usuario */ private Organism[] getOrganisms(String tokenJwt) { UserSearch userSearch = new UserSearch(); userSearch.setNif(idUser); ParamAdditionalDataOrganismListByUser paramAdditionalDataOrganismListByUser = new ParamAdditionalDataOrganismListByUser(userSearch); paramAdditionalDataOrganismListByUser.setApplicationId(idApplicationSIU); ResultAdditionalDataOrganismListByUser result = new ResultAdditionalDataOrganismListByUser(); result = siuAgent.additionalDataOrganismListByUser(paramAdditionalDataOrganismListByUser); OrganismByUser[] organismsByUser = result.getOrganismByUser(); Organism[] listOrganism = OrganismAdditionalDataToOrganism(organisms[0].getOrganisms()); return listOrganism; }
1.2.- Ejemplo identificación 2: cierre de sesión en un portal.
El portal de ejemplo utiliza el framework Struts2. Cuando se realiza el 'logout' se invalida la sesión, se
preparan los datos para la identificación y se dirige a la página de login.
-1.2.1.- Cierre de sesión antes de integración con MFE – Identificación
/** * Método que realiza el cierre de sesión de la aplicación. * @return retorno de logout para struts2 */ public final String logOut() { // Se invalida la sesión request.getSession().invalidate(); // Preparación para antigua identificación // Se preparan los datos para firmar por el usuario en el login String token = new Date().toString(); this.getServletRequest().getSession().setAttribute("token", token); // Recuperamos las Cas para mostrar los certificados en el login getArrayCAs(getCAs()); return SUCCESS; }
<!-- LogIn/LogOut --> <action name="login_*" method="{1}" class="loginAction"> <result name="success">login.jsp</result> <result name="second">login.jsp</result> <result name="notificationList" type="redirect-action">notificationList_search</result> </action>
-
1.2.2.- Cierre de sesión después de integración con MFE – Identificación
Una vez invalidada la sesión se redireccionará al método de logout de MFE (que volverá a la página de login) en vez de ir directamente a la página de login de la aplicación
/** * Método que realiza el cierre de sesión de la aplicación. * @return retorno de logout para struts2 */ public final String logOut() { // Se invalida la sesión request.getSession().invalidate(); // Se obtiene la url para invocar a MFE y realizar logout (se pasa al fichero struts.xml) urlLogoutMFE = getUrlLogOutMFE(applicationId, (String) request.getSession().getAttribute("identificationMethod")); return “logout”; } /** * Método que devuelve la url para invocar al método logout de MFE: * @param applicationId identificador de la aplicación en MFE * @param identificationMethod método con el que el usuario se ha idntificado * @return url para invocar a * @throws UnsupportedEncodingException */ private String getUrlLogOutMFE(String applicationId, String identificationMethod) { // [URL_SERV]/mfe_core/rest/identification/[APPLICATION_ID] String urlLogoutMFE = "http://integracion/mfe_core/rest/identification/" + applicationId; // [APPLICATION_URL_REDIRECT] urlLogoutMFE += new String(Base64.encodeBase64(("http://integracion/snt_pf_v3/login_goToLogin.action").getBytes("UTF8")), "UTF-8"); // [IDENTIFICATION_MEHTOD_ID]/logout urlLogoutMFE += "/" + request.getSession().getAttribute("identificationMethod") + "/logout"; return urlLogoutMFE; }
<!-- LogIn/LogOut --> <action name="login_*" method="{1}" class="loginAction"> <result name="success">login.jsp</result> <result name="second">login.jsp</result> <result name="notificationList" type="redirect-action">notificationList_search</result> <result name="logout" type="redirect">${urlLogoutMFE}</result> </action>
2.- MFE - Módulo de firma cliente:
2.1.- Ejemplo firma cliente 1: firma simple Cades-Bes y filtrado de usuario
El siguiente código es un ejemplo de integración con MFE - Firma cliente. Requiere conexión con MFE y estar desplegado en un servidor de aplicaciones con un dominio aceptado por MFE. Este ejemplo vale para filtrar los certificados por usuario identificado en el sistema mediante MFE como para mostrar todos los certificados que el usuario tiene instalados en su navegador
Esta operación realiza una firma simple en formato CadES-BES con algoritmo SHA1withRSA en modo Detached. Para ello como datos a firmar envía el hash (SHA1) del documento codificado en base64.
<html> <head> <title>MFE Signature test</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <!-- MFE 1) Etiqueta de compatiblidad ie--> <meta http-equiv="X-UA-Compatible" content="requiresActiveX=true"/> <!-- MFE 2) Javascript para firma en cliente --> <script type="text/javascript" src="http://integracion/mfe_core/js/mfe_clientSignature.js"></script> <script type="text/javascript"> // MFE 6) Función para para recoger la firma. // En este ejemplo escondemos el iframe de firma y mostramos el resultado. function signatureSuccess(signatureB64) { console.log("[APP TEST] signatureSuccess!!"); document.getElementById("resulSignatureDiv").style.display = "block"; document.getElementById("signatureDiv").style.display = "none"; document.getElementById("resultMessage").innerHTML = "La firma se ha realizado satisfactoriamente"; document.getElementById("signature").innerHTML = "<strong>FIRMA DEL DOCUMENTO: </strong><br>" + signatureB64; } // MFE 7) Función para para recoger posible error durante la firma // En nuestro ejemplo escondemos el iframe de firma y mostramos el resultado. function signatureError(type, message) { console.error("[APP TEST] signatureError. Message: " + message + ", type: " + type); document.getElementById("resulSignatureDiv").style.display = "block"; document.getElementById("signatureDiv").style.display = "none"; document.getElementById("resultMessage").innerHTML = "ERROR al firmar. Mensaje: " + message + ", tipo: " + type; } </script> </head> <body> <h1 align="center">Firma de documentos</h1> <!-- Div donde mostramos el iframe para la firma en cliente --> <div id='signatureDiv' align="center" ><div> <label> Seleccione el método de firma que desee: </label> </div> <div> <!-- MFE 3) iframe de firma cliente --> <iframe id="mfeClientSignatureIframe" src="http://integracion/mfe_core/rest/clientSignature/APP_TEST/firma_cades_detached_hash" width=750px height=300px frameBorder="0"> </iframe> <!-- MFE 4) hash del documento a firmar (calculado con algoritmo SHA1 ya que la firma se realizará con algoritmo de firma SHA1)--> <input id="mfeDataToSign" type="hidden" value="8pHUMKFll9B0kdhd8CPK1kmAJtU="> </div> </div> <!-- Div donde mostramos el resultado de la firma en cliente --> <div id='resulSignatureDiv' align="center" style="display:none"> <div id="resultMessage" align="center"></div> <div id="originalDataSigned" align="left"> <strong>DOCUMENTO ORIGINAL: </strong> <br>Cadena de texto de prueba para firma </div> <br><br><br> <div id="signature"align="left"></div> </div> </body> </html>
2.1.- Ejemplo firma cliente 1: multifirma paralela Cades-Bes y filtrado de usuario
El siguiente código es un ejemplo de integración con MFE - Firma cliente. Requiere conexión con MFE y estar desplegado en un servidor de aplicaciones con un dominio aceptado por MFE.
Este ejemplo solamente es valido para filtrar los certificados por usuario distinto al identificado mediante MFE o para una aplicación que no tiene identificación mediante MFE.
Esta operación realiza una firma múltiple paralela en formato CadES-BES con algoritmo SHA1withRSA en modo Detached. Para ello como datos a firmar envía el hash (SHA1) del documento codificado en base64 y la firma realizada previamente en base64.
<html> <head> <title>MFE Signature test</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <!-- MFE 1) Etiqueta de compatiblidad ie--> <meta http-equiv="X-UA-Compatible" content="requiresActiveX=true"/> <!-- MFE 2) Javascript para firma en cliente --> <script type="text/javascript" src="http://integracion/mfe_core/js/mfe_clientSignature.js"></script> <script type="text/javascript"> // MFE 6) Función para para recoger la firma. // En este ejemplo escondemos el iframe de firma y mostramos el resultado. function signatureSuccess(signatureB64) { console.log("[APP TEST] signatureSuccess!!"); document.getElementById("resulSignatureDiv").style.display = "block"; document.getElementById("signatureDiv").style.display = "none"; document.getElementById("resultMessage").innerHTML = "La firma se ha realizado satisfactoriamente"; document.getElementById("signature").innerHTML = "<strong>FIRMA DEL DOCUMENTO: </strong><br>" + signatureB64; } // MFE 7) Función para para recoger posible error durante la firma // En nuestro ejemplo escondemos el iframe de firma y mostramos el resultado. function signatureError(type, message){ console.error("[APP TEST] signatureError. Message: " + message + ", type: " + type); document.getElementById("resulSignatureDiv").style.display = "block"; document.getElementById("signatureDiv").style.display = "none"; document.getElementById("resultMessage").innerHTML = "ERROR al firmar. Mensaje: " + message + ", tipo: " + type; } </script> </head> <body> <h1 align="center">Firma de documentos</h1> <!-- Div donde mostramos el iframe para la firma en cliente --> <div id='signatureDiv' align="center" > <div> <label> Seleccione el método de firma que desee: </label> </div> <div> <!-- MFE 3) iframe de firma cliente --> <iframe id="mfeClientSignatureIframe" src="http://integracion/mfe_core/rest/clientSignature/APP_TEST/firma_cades_detached_hash" width=750px height=300px frameBorder="0"> </iframe> <!-- MFE 4) hash del documento a firmar (calculado con algoritmo SHA1 ya que la firma se realizará con algoritmo de firma SHA1)--> <input id="mfeDataToSign" type="hidden" value="8pHUMKFll9B0kdhd8CPK1kmAJtU="> <!-- MFE 4) firma en b64 donde se incluirá la nueva firma--> <input id="mfeSignature" type="hidden" value="MIIXZgYJKoZIhvcNAQcCoIIXVzCCF1NVzCC(...)"> <!-- MFE 5) Filtrado por usuario no identificado mediante MFE --> <input id="mfeIdUser" type="hidden" value="11111111H"> </div> </div> <!-- Div donde mostramos el resultado de la firma en cliente --> <div id='resulSignatureDiv' align="center" style="display:none"> <div id="resultMessage" align="center"></div> <div id="originalDataSigned" align="left"> <strong>DOCUMENTO ORIGINAL: </strong> <br>Cadena de texto de prueba para firma </div> <br><br><br> <div id="signature"align="left"></div> </div> </body> </html>