Java tutorial
/* Copyright (C) 2007 Flix Garca Borrego (borrego at gmail.com) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package org.viafirma.nucleo.autenticacion.imp; import java.io.IOException; import java.security.cert.X509Certificate; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.viafirma.excepciones.CodigoError; import org.viafirma.nucleo.Nucleo; import org.viafirma.nucleo.autenticacion.AutenticacionBridge; import org.viafirma.util.FaceletsUtil; import org.viafirma.util.XmlSignUtil; /** * Implementacin especfica encargada de la recuperacin del certificado del cliente. * Esta implementacin se basa en el uso de un Applet para recuperar el * certificado. * * @author Felix Garcia Borrego (borrego at gmail.com) */ public class AutenticacionAppletBridgeImp extends HttpServlet implements AutenticacionBridge { /** * */ private static final long serialVersionUID = 1L; /** * Logger. */ private Log log = LogFactory.getLog(AutenticacionAppletBridgeImp.class); /** * URI a la que se redirecciona para autenticar al usuario */ public static final String URI_AUTENTICACION = "/autenticacionApplet/login.jsf"; private static AutenticacionAppletBridgeImp singleton = new AutenticacionAppletBridgeImp(); /** * Recupera la nica instancia del bridge. Basandose en el patron singleton * * @return Instancia de la bridge */ public static AutenticacionAppletBridgeImp getInstance() { return singleton; } /** * Crea una nueva instancia. Este mtodo solo es admisible que sea llamado * desde el Contenedor de servlet para crear el servlet. * */ public AutenticacionAppletBridgeImp() { super(); // debe ser pblica por ser un Servlet( esto hace que el singleton se // vea modificado) } /*** * Para solicitar el certificado redirecciona al cliente a una pgina que * contiene un Applet que solicita al usuario su certificado. * * @see org.viafirma.nucleo.autenticacion.AutenticacionBridge#generarSolicitudCertificado(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ public void generarSolicitudCertificado(HttpServletRequest request, HttpServletResponse response) { log.debug("Iniciando solicitud de certificado"); // almaceno el identificador de sessin( posteriormente se utiliza para // cachear los diferentes certificados) request.setAttribute("sessionID", request.getSession().getId()); FaceletsUtil.forward(request, response, URI_AUTENTICACION); } /** * Este mtodo es invocado por el Applet de autenticacin cuando completa la * autenticacin. El mtodo recupera el identificador de sessin para * identificar este identificador con la peticin y redirecciona al nucleo * para que procese el certificado. * * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String resultado = request.getParameter("result"); Nucleo nucleo = Nucleo.getInstance(); if ("OK".equalsIgnoreCase(resultado)) { // El applet recupero correctamente el certificado y este fue // almacenado correctamente por el nucleo log.debug("El certificado ha sido ya recuperado, iniciamos su validacin"); String sessionID = request.getParameter(Nucleo.SESSION_ID); // comprobamos el certificado y si todo esta correcto // redireccionamos nucleo.finAutenticacion(sessionID, request, response); } else if ("errorVerificacion".equalsIgnoreCase(resultado)) { // El certificado no es vlido nucleo.redireccionarError(CodigoError.ERROR_CERTIFICADO_NO_VALIDO, request, response); } else if ("error".equalsIgnoreCase(resultado)) { // se ha producido algun error lo enviamos a una pgina de error // informando de lo sucedido nucleo.redireccionarError(CodigoError.ERROR_CERTIFICADO_NO_FOUND, request, response); } else if ("cancel".equalsIgnoreCase(resultado)) { // El usuario ha cancelado y no ha enviado ningun certificado al // servidor. nucleo.redireccionarError(CodigoError.WARNING_CERTIFICADO_NO_ENVIADO, request, response); } else { log.error("Resultado no esperado:" + resultado); throw new ServletException("Resultado no espsrado :" + resultado); } } /** * Este mtodo es invocado por el Applet de autenticacin cuando recupera el * certificado. Recuperamos el certificado enviado por el applet( dentro de * un XML-sig), lo procesamos y lo almacenamod en la cache para que sea * recuperado posteriormente por el Nucleo. * * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String resultado = request.getParameter("result"); if ("OK".equalsIgnoreCase(resultado)) { // el applet ha podido recuperar el certificado correctamente, // iniciamos el proceso de autenticacin y validacin log("El usuario ha indicado un certificado"); recuperarCertificado(request, response); } else { // el certificado no ha podido ser recuperado por el certificado log("El usuario no ha indicado un certificado"); } } /** * Recupera el certificado enviado por el navegador y lo almacena en el * nucleo. * * Proceso: * * <pre> * 1.- Recupera el XmlSignature desde el parametro message * 2.- Desde el XmlSignature recupera el X509Certificado * 3.- Se lo pasa al ncleo para que lo valide. * </pre> * * @param request * @param response * @throws ServletException */ private void recuperarCertificado(HttpServletRequest request, HttpServletResponse response) throws ServletException { try { // certificado en xml codificado en base 64 String xmldoc_b64 = request.getParameter("message"); // recupero el identificador de sessin con el que posteriormente // poder identificar este objeto. String sessionID = request.getParameter("sessionID"); XmlSignUtil xmlSignParser = XmlSignUtil.getInstance(); // recupero el XmlSignature generado por el applet de autenticacin // ( Siempre tiene que aparecer 1 X509Certificate certificadoX509 = xmlSignParser.parseCertificado(xmldoc_b64).get(0); // mostramos el certificado recuperado if (log.isDebugEnabled()) { log.debug("Recuperado certificado " + certificadoX509.getIssuerDN().getName()); } // enviamos el certificado al ncleo para que este compruebe la // validez del mismo Nucleo nucleo = Nucleo.getInstance(); // almacena el certificado recuperado en el ncleo para su // procesamiento posterior. nucleo.cachearCertificado(sessionID, certificadoX509); } catch (Exception e) { throw new ServletException(e); } } }