From 6ea2c1db26260c1f36e01c58fc6f8ef0220e577e Mon Sep 17 00:00:00 2001 From: Andreas Fitzek Date: Thu, 5 Jun 2014 10:46:34 +0200 Subject: SOAP Service for backend upload + transaction ID fixes --- .../gv/egiz/pdfas/web/config/WebConfiguration.java | 13 +++ .../pdfas/web/exception/PdfAsStoreException.java | 17 +++ .../at/gv/egiz/pdfas/web/helper/PdfAsHelper.java | 44 ++++++-- .../pdfas/web/helper/PdfAsParameterExtractor.java | 6 ++ .../egiz/pdfas/web/servlets/ExternSignServlet.java | 4 +- .../pdfas/web/servlets/UIEntryPointServlet.java | 117 +++++++++++++++++++++ .../at/gv/egiz/pdfas/web/store/IRequestStore.java | 8 ++ .../egiz/pdfas/web/store/InMemoryRequestStore.java | 31 ++++++ .../at/gv/egiz/pdfas/web/store/RequestStore.java | 35 ++++++ .../at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java | 22 +++- 10 files changed, 287 insertions(+), 10 deletions(-) create mode 100644 pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/exception/PdfAsStoreException.java create mode 100644 pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/UIEntryPointServlet.java create mode 100644 pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/IRequestStore.java create mode 100644 pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/InMemoryRequestStore.java create mode 100644 pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/RequestStore.java (limited to 'pdf-as-web/src/main/java/at') diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/WebConfiguration.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/WebConfiguration.java index 4555d6a1..299c166f 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/WebConfiguration.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/WebConfiguration.java @@ -56,6 +56,9 @@ public class WebConfiguration { public static final String WHITELIST_ENABLED = "whitelist.enabled"; public static final String WHITELIST_VALUE_PRE = "whitelist.url."; + public static final String REQUEST_STORE = "request.store"; + public static final String REQUEST_STORE_INMEM = "at.gv.egiz.pdfas.web.store.InMemoryRequestStore"; + private static Properties properties = new Properties(); private static final Logger logger = LoggerFactory @@ -211,4 +214,14 @@ public class WebConfiguration { } return true; } + + public static String getStoreClass() { + String cls = properties.getProperty(REQUEST_STORE); + + if(cls != null) { + return cls; + } + + return REQUEST_STORE_INMEM; + } } diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/exception/PdfAsStoreException.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/exception/PdfAsStoreException.java new file mode 100644 index 00000000..f4c70278 --- /dev/null +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/exception/PdfAsStoreException.java @@ -0,0 +1,17 @@ +package at.gv.egiz.pdfas.web.exception; + +public class PdfAsStoreException extends Exception { + + /** + * + */ + private static final long serialVersionUID = -6704586769888839023L; + + public PdfAsStoreException(String message) { + super(message); + } + + public PdfAsStoreException(String message, Throwable e) { + super(message, e); + } +} diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java index ee67985b..421edff4 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java @@ -25,6 +25,8 @@ package at.gv.egiz.pdfas.web.helper; import java.io.File; import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.util.Iterator; import java.util.List; @@ -57,9 +59,9 @@ import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter; import at.gv.egiz.pdfas.lib.api.verify.VerifyResult; import at.gv.egiz.pdfas.sigs.pades.PAdESSigner; import at.gv.egiz.pdfas.sigs.pades.PAdESSignerKeystore; -import at.gv.egiz.pdfas.sigs.pkcs7detached.PKCS7DetachedSigner; import at.gv.egiz.pdfas.web.config.WebConfiguration; import at.gv.egiz.pdfas.web.exception.PdfAsWebException; +import at.gv.egiz.pdfas.web.servlets.UIEntryPointServlet; import at.gv.egiz.sl.schema.CreateCMSSignatureResponseType; import at.gv.egiz.sl.schema.InfoboxAssocArrayPairType; import at.gv.egiz.sl.schema.InfoboxReadRequestType; @@ -84,6 +86,7 @@ public class PdfAsHelper { private static final String PDF_PROVIDE_PAGE = "/ProvidePDF"; private static final String PDF_PDFDATA_PAGE = "/PDFData"; private static final String PDF_DATAURL_PAGE = "/DataURL"; + private static final String PDF_USERENTRY_PAGE = "/userentry"; private static final String PDF_ERR_URL = "PDF_ERR_URL"; private static final String PDF_FILE_NAME = "PDF_FILE_NAME"; private static final String PDF_INVOKE_URL = "PDF_INVOKE_URL"; @@ -384,7 +387,8 @@ public class PdfAsHelper { } public static void startSignature(HttpServletRequest request, - HttpServletResponse response, ServletContext context, byte[] pdfData) + HttpServletResponse response, ServletContext context, byte[] pdfData, + String connector, String transactionId) throws Exception { // TODO: Protect session so that only one PDF can be signed during one @@ -409,9 +413,10 @@ public class PdfAsHelper { SignParameter signParameter = PdfAsFactory.createSignParameter(config, new ByteArrayDataSource(pdfData)); - // Get Connector - String connector = PdfAsParameterExtractor.getConnector(request); - + logger.info("Setting TransactionID: " + transactionId); + + signParameter.setTransactionId(transactionId); + IPlainSigner signer; if (connector.equals("bku") || connector.equals("onlinebku") || connector.equals("mobilebku")) { @@ -535,7 +540,7 @@ public class PdfAsHelper { logger.debug("Needing Certificate from BKU"); // build SL Request to read certificate InfoboxReadRequestType readCertificateRequest = bkuSLConnector - .createInfoboxReadRequest(); + .createInfoboxReadRequest(statusRequest.getSignParameter()); JAXBElement readRequest = of .createInfoboxReadRequest(readCertificateRequest); @@ -548,6 +553,14 @@ public class PdfAsHelper { template = template.replace("##XMLRequest##", StringEscapeUtils.escapeHtml4(slRequest)); template = template.replace("##DataURL##", url); + + if(statusRequest.getSignParameter().getTransactionId() != null) { + template = template.replace("##ADDITIONAL##", ""); + } else { + template = template.replace("##ADDITIONAL##", ""); + } + response.getWriter().write(template); //TODO: set content type of response!! response.setContentType("text/html"); @@ -557,7 +570,8 @@ public class PdfAsHelper { // build SL Request for cms signature RequestPackage pack = bkuSLConnector .createCMSRequest(statusRequest.getSignatureData(), - statusRequest.getSignatureDataByteRange()); + statusRequest.getSignatureDataByteRange(), + statusRequest.getSignParameter()); String slRequest = SLMarschaller .marshalToString(of @@ -775,6 +789,22 @@ public class PdfAsHelper { HttpServletResponse response) { return generateURL(request, response, PDF_PDFDATA_PAGE); } + + public static String generateUserEntryURL(String storeId) { + String publicURL = WebConfiguration.getPublicURL(); + if(publicURL == null) { + logger.error("To use this functionality " + WebConfiguration.PUBLIC_URL + " has to be configured in the web configuration"); + return null; + } + + String baseURL = publicURL + PDF_USERENTRY_PAGE; + try { + return baseURL + "?" + UIEntryPointServlet.REQUEST_ID_PARAM + "=" + URLEncoder.encode(storeId, "UTF-8"); + } catch(UnsupportedEncodingException e) { + logger.warn("Encoding not supported for URL encoding", e); + } + return baseURL + "?" + UIEntryPointServlet.REQUEST_ID_PARAM + "=" + storeId; + } public static String generateBKUURL(String connector) { if (connector.equals("bku")) { diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsParameterExtractor.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsParameterExtractor.java index 730fe9ad..126b10ce 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsParameterExtractor.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsParameterExtractor.java @@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest; public class PdfAsParameterExtractor { public static final String PARAM_CONNECTOR = "connector"; + public static final String PARAM_TRANSACTION_ID = "transactionId"; public static final String PARAM_CONNECTOR_DEFAULT = "bku"; @@ -53,6 +54,11 @@ public class PdfAsParameterExtractor { return PARAM_CONNECTOR_DEFAULT; } + public static String getTransactionId(HttpServletRequest request) { + String transactionId = (String)request.getAttribute(PARAM_TRANSACTION_ID); + return transactionId; + } + public static String getInvokeURL(HttpServletRequest request) { return (String)request.getAttribute(PARAM_INVOKE_URL); } diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java index 153a69fe..a7d82c3e 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java @@ -238,6 +238,8 @@ public class ExternSignServlet extends HttpServlet { HttpServletResponse response, byte[] pdfData) throws Exception { // Get Connector String connector = PdfAsParameterExtractor.getConnector(request); + + String transactionId = PdfAsParameterExtractor.getTransactionId(request); String invokeUrl = PdfAsParameterExtractor.getInvokeURL(request); PdfAsHelper.setInvokeURL(request, response, invokeUrl); @@ -278,7 +280,7 @@ public class ExternSignServlet extends HttpServlet { } } - PdfAsHelper.startSignature(request, response, getServletContext(), pdfData); + PdfAsHelper.startSignature(request, response, getServletContext(), pdfData, connector, transactionId); } else if (connector.equals("jks") || connector.equals("moa")) { // start synchronous siganture creation diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/UIEntryPointServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/UIEntryPointServlet.java new file mode 100644 index 00000000..3aad5abb --- /dev/null +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/UIEntryPointServlet.java @@ -0,0 +1,117 @@ +package at.gv.egiz.pdfas.web.servlets; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.http.HttpStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.api.ws.PDFASSignRequest; +import at.gv.egiz.pdfas.api.ws.PDFASSignParameters.Connector; +import at.gv.egiz.pdfas.common.exceptions.PdfAsException; +import at.gv.egiz.pdfas.web.config.WebConfiguration; +import at.gv.egiz.pdfas.web.exception.PdfAsStoreException; +import at.gv.egiz.pdfas.web.exception.PdfAsWebException; +import at.gv.egiz.pdfas.web.helper.DigestHelper; +import at.gv.egiz.pdfas.web.helper.PdfAsHelper; +import at.gv.egiz.pdfas.web.helper.PdfAsParameterExtractor; +import at.gv.egiz.pdfas.web.store.RequestStore; + +public class UIEntryPointServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + public static final String REQUEST_ID_PARAM = "reqId"; + + private static final Logger logger = LoggerFactory + .getLogger(UIEntryPointServlet.class); + + public UIEntryPointServlet() { + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + doProcess(req, resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + doProcess(req, resp); + } + + protected void doProcess(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + try { + String storeId = req.getParameter(REQUEST_ID_PARAM); + + if (storeId == null) { + throw new PdfAsStoreException("Wrong Parameters"); + } + + PDFASSignRequest pdfAsRequest = RequestStore.getInstance() + .fetchStoreEntry(storeId); + + if(pdfAsRequest == null) { + throw new PdfAsStoreException("Invalid " + REQUEST_ID_PARAM + " value"); + } + + Connector connector = pdfAsRequest.getParameters().getConnector(); + + String invokeUrl = pdfAsRequest.getParameters().getInvokeURL(); + PdfAsHelper.setInvokeURL(req, resp, invokeUrl); + + String errorUrl = pdfAsRequest.getParameters().getInvokeErrorURL(); + PdfAsHelper.setErrorURL(req, resp, errorUrl); + + if(pdfAsRequest.getInputData() == null) { + throw new PdfAsException("No Signature data available"); + } + + String pdfDataHash = DigestHelper.getHexEncodedHash(pdfAsRequest.getInputData()); + + PdfAsHelper.setSignatureDataHash(req, pdfDataHash); + logger.debug("Storing signatures data hash: " + pdfDataHash); + + logger.debug("Starting signature creation with: " + connector); + + //IPlainSigner signer; + if (connector.equals(Connector.BKU) || connector.equals(Connector.ONLINEBKU) || connector.equals(Connector.MOBILEBKU)) { + // start asynchronous signature creation + + if(connector.equals(Connector.BKU)) { + if(WebConfiguration.getLocalBKUURL() == null) { + throw new PdfAsWebException("Invalid connector bku is not supported"); + } + } + + if(connector.equals(Connector.ONLINEBKU)) { + if(WebConfiguration.getLocalBKUURL() == null) { + throw new PdfAsWebException("Invalid connector onlinebku is not supported"); + } + } + + if(connector.equals(Connector.MOBILEBKU)) { + if(WebConfiguration.getLocalBKUURL() == null) { + throw new PdfAsWebException("Invalid connector mobilebku is not supported"); + } + } + + PdfAsHelper.startSignature(req, resp, getServletContext(), pdfAsRequest.getInputData(), + connector.toString(), pdfAsRequest.getParameters().getTransactionId()); + } else { + throw new PdfAsWebException("Invalid connector (" + Connector.BKU + " | " + Connector.ONLINEBKU + " | " + Connector.MOBILEBKU + ")"); + } + + + } catch (Throwable e) { + PdfAsHelper.setSessionException(req, resp, e.getMessage(), e); + PdfAsHelper.gotoError(getServletContext(), req, resp); + } + } +} diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/IRequestStore.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/IRequestStore.java new file mode 100644 index 00000000..6623004b --- /dev/null +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/IRequestStore.java @@ -0,0 +1,8 @@ +package at.gv.egiz.pdfas.web.store; + +import at.gv.egiz.pdfas.api.ws.PDFASSignRequest; + +public interface IRequestStore { + public String createNewStoreEntry(PDFASSignRequest request); + public PDFASSignRequest fetchStoreEntry(String id); +} diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/InMemoryRequestStore.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/InMemoryRequestStore.java new file mode 100644 index 00000000..df9ab676 --- /dev/null +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/InMemoryRequestStore.java @@ -0,0 +1,31 @@ +package at.gv.egiz.pdfas.web.store; + +import java.util.HashMap; +import java.util.UUID; + +import at.gv.egiz.pdfas.api.ws.PDFASSignRequest; + +public class InMemoryRequestStore implements IRequestStore { + + public InMemoryRequestStore() { + } + + private HashMap store = new HashMap(); + + public String createNewStoreEntry(PDFASSignRequest request) { + UUID id = UUID.randomUUID(); + String sid = id.toString(); + this.store.put(sid, request); + return sid; + } + + public PDFASSignRequest fetchStoreEntry(String id) { + if(store.containsKey(id)) { + PDFASSignRequest request = store.get(id); + store.remove(id); + return request; + } + return null; + } + +} diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/RequestStore.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/RequestStore.java new file mode 100644 index 00000000..a4eba2e6 --- /dev/null +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/RequestStore.java @@ -0,0 +1,35 @@ +package at.gv.egiz.pdfas.web.store; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.web.config.WebConfiguration; +import at.gv.egiz.pdfas.web.exception.PdfAsStoreException; + +public class RequestStore { + private static IRequestStore instance = null; + + private static final Logger logger = LoggerFactory + .getLogger(RequestStore.class); + + public synchronized static IRequestStore getInstance() throws PdfAsStoreException { + if (instance == null) { + try { + String storeClass = WebConfiguration.getStoreClass(); + logger.info("Using Request Store: " + storeClass); + + Class clazz = Class.forName(storeClass); + Object store = clazz.newInstance(); + if(store instanceof IRequestStore) { + instance = (IRequestStore)store; + } else { + throw new PdfAsStoreException("Failed to instanciate Request Store from " + storeClass); + } + } catch (Throwable e) { + e.printStackTrace(); + throw new PdfAsStoreException("Failed to instanciate Request Store", e); + } + } + return instance; + } +} diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java index 07ffd7c4..5304f918 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java @@ -16,8 +16,10 @@ import at.gv.egiz.pdfas.api.ws.PDFASSignParameters; import at.gv.egiz.pdfas.api.ws.PDFASSignRequest; import at.gv.egiz.pdfas.api.ws.PDFASSignResponse; import at.gv.egiz.pdfas.api.ws.PDFASSigning; +import at.gv.egiz.pdfas.api.ws.PDFASSignParameters.Connector; import at.gv.egiz.pdfas.web.config.WebConfiguration; import at.gv.egiz.pdfas.web.helper.PdfAsHelper; +import at.gv.egiz.pdfas.web.store.RequestStore; @MTOM @WebService(endpointInterface = "at.gv.egiz.pdfas.api.ws.PDFASSigning") @@ -25,7 +27,7 @@ public class PDFASSigningImpl implements PDFASSigning { private static final Logger logger = LoggerFactory .getLogger(PDFASSigningImpl.class); - + public byte[] signPDFDokument(byte[] inputDocument, PDFASSignParameters parameters) { checkSoapSignEnabled(); @@ -50,8 +52,24 @@ public class PDFASSigningImpl implements PDFASSigning { } PDFASSignResponse response = new PDFASSignResponse(); try { - response.setSignedPDF(signPDFDokument(request.getInputData(), + if(request.getParameters().getConnector().equals(Connector.MOA) || + request.getParameters().getConnector().equals(Connector.JKS)) { + // Plain server based signatures!! + response.setSignedPDF(signPDFDokument(request.getInputData(), request.getParameters())); + } else { + // Signatures with user interaction!! + String id = RequestStore.getInstance().createNewStoreEntry(request); + String userEntryURL = PdfAsHelper.generateUserEntryURL(id); + logger.debug("Generated request store: " + id); + logger.debug("Generated UI URL: " + userEntryURL); + + if(userEntryURL == null) { + throw new WebServiceException("Failed to generate User Entry URL"); + } + + response.setRedirectUrl(userEntryURL); + } } catch (Throwable e) { if (e.getCause() != null) { response.setError(e.getCause().getMessage()); -- cgit v1.2.3