From 06cf27605579abab9d18615d1fef701b941e06f6 Mon Sep 17 00:00:00 2001 From: Andreas Fitzek Date: Mon, 27 Jun 2016 16:04:53 +0200 Subject: added JSON API, added keep signed data flag for configuration --- .../gv/egiz/pdfas/web/servlets/JSONAPIServlet.java | 255 +++++++++++++++++++++ .../at/gv/egiz/pdfas/web/servlets/PDFData.java | 20 +- 2 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/JSONAPIServlet.java (limited to 'pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets') diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/JSONAPIServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/JSONAPIServlet.java new file mode 100644 index 00000000..1b9b4560 --- /dev/null +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/JSONAPIServlet.java @@ -0,0 +1,255 @@ +package at.gv.egiz.pdfas.web.servlets; + +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.VerificationLevel; +import at.gv.egiz.pdfas.common.exceptions.PDFASError; +import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter; +import at.gv.egiz.pdfas.lib.api.verify.VerifyResult; +import at.gv.egiz.pdfas.web.config.WebConfiguration; +import at.gv.egiz.pdfas.web.exception.PdfAsWebException; +import at.gv.egiz.pdfas.web.filter.UserAgentFilter; +import at.gv.egiz.pdfas.web.helper.DigestHelper; +import at.gv.egiz.pdfas.web.helper.JSONStartResponse; +import at.gv.egiz.pdfas.web.helper.PdfAsHelper; +import at.gv.egiz.pdfas.web.stats.StatisticEvent; +import at.gv.egiz.pdfas.web.stats.StatisticFrontend; +import at.gv.egiz.pdfas.web.store.RequestStore; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.IOUtils; +import org.json.HTTP; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.ws.WebServiceException; +import java.io.BufferedReader; +import java.io.IOException; +import java.util.List; +import java.util.Map; + +/** + * Created by Andreas Fitzek on 6/23/16. + */ +public class JSONAPIServlet extends HttpServlet { + + private static final String JSON_PROFILE = "profile"; + private static final String JSON_POSITION = "position"; + private static final String JSON_CONNECTOR = "connector"; + private static final String JSON_REQUEST_ID = "reqID"; + private static final String JSON_INPUT = "input"; + private static final String JSON_OUTPUT = "output"; + private static final String JSON_OUTPUT_SIG = "verifySignature"; + private static final String JSON_OUTPUT_CER = "verifyCertificate"; + private static final String JSON_DATAURL = "dataUrl"; + private static final String JSON_BKUURL = "bkuUrl"; + private static final String JSON_SLREQUEST = "slRequest"; + + private static final Logger logger = LoggerFactory.getLogger(JSONAPIServlet.class); + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + + String jsonString = IOUtils.toString(req.getInputStream(), "UTF-8"); + + logger.debug("Reading json String {}", jsonString); + + JSONObject jsonObject = new JSONObject(jsonString); + + logger.debug("JSON parsed: {}", jsonObject.toString()); + + process(req, resp, jsonObject); + } + + protected void process(HttpServletRequest request, + HttpServletResponse response, + JSONObject jsonObject) throws ServletException, IOException { + + JSONObject jsonResponse = new JSONObject(); + + + + String profile = jsonObject.has(JSON_PROFILE) ? jsonObject.getString(JSON_PROFILE) : null; + String position = jsonObject.has(JSON_POSITION) ? jsonObject.getString(JSON_POSITION) : null; + String connector = jsonObject.getString(JSON_CONNECTOR); + String input = jsonObject.getString(JSON_INPUT); + String requestID = jsonObject.has(JSON_REQUEST_ID) ? jsonObject.getString(JSON_REQUEST_ID) : null; + + if(input == null) { + throw new ServletException( + "Invalid input value!"); + } + + byte[] inputDocument = Base64.decodeBase64(input); + + StatisticEvent statisticEvent = new StatisticEvent(); + statisticEvent.setSource(StatisticEvent.Source.JSON); + statisticEvent.setOperation(StatisticEvent.Operation.SIGN); + statisticEvent.setUserAgent(UserAgentFilter.getUserAgent()); + statisticEvent.setStartNow(); + + try { + + if(connector == null) { + throw new ServletException( + "Invalid connector value!"); + } + + PDFASSignParameters.Connector connectorEnum = null; + + if(PDFASSignParameters.Connector.MOA.equalsName(connector)) { + connectorEnum = PDFASSignParameters.Connector.MOA; + } else if(PDFASSignParameters.Connector.JKS.equalsName(connector)) { + connectorEnum = PDFASSignParameters.Connector.JKS; + } else if(PDFASSignParameters.Connector.BKU.equalsName(connector)) { + connectorEnum = PDFASSignParameters.Connector.BKU; + } else if(PDFASSignParameters.Connector.MOBILEBKU.equalsName(connector)) { + connectorEnum = PDFASSignParameters.Connector.MOBILEBKU; + } else if(PDFASSignParameters.Connector.ONLINEBKU.equalsName(connector)) { + connectorEnum = PDFASSignParameters.Connector.ONLINEBKU; + } + + if(connectorEnum == null) { + throw new ServletException( + "Invalid connector value!"); + } + + // TODO: check connector is enabled! + + statisticEvent.setFilesize(inputDocument.length); + statisticEvent.setProfileId(profile); + statisticEvent.setDevice(connector); + + PDFASSignParameters parameters = new PDFASSignParameters(); + parameters.setConnector(connectorEnum); + parameters.setPosition(position); + parameters.setProfile(profile); + + if (PDFASSignParameters.Connector.MOA.equals(connectorEnum) + || PDFASSignParameters.Connector.JKS.equals(connectorEnum)) { + // Plain server based signatures!! + PDFASSignResponse pdfasSignResponse = PdfAsHelper.synchornousServerSignature( + inputDocument, parameters); + + VerifyResult verifyResult = null; + + List verResults = PdfAsHelper + .synchornousVerify( + pdfasSignResponse.getSignedPDF(), + -1, + VerifyParameter.SignatureVerificationLevel.INTEGRITY_ONLY_VERIFICATION, + null); + + if (verResults.size() != 1) { + throw new ServletException( + "Document verification failed!"); + } + verifyResult = verResults.get(0); + + if(verifyResult.getValueCheckCode().getCode() == 0) { + statisticEvent.setStatus(StatisticEvent.Status.OK); + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + } else { + statisticEvent.setStatus(StatisticEvent.Status.ERROR); + statisticEvent.setErrorCode(verifyResult.getValueCheckCode().getCode()); + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + } + + jsonResponse.put(JSON_OUTPUT, Base64.encodeBase64String(pdfasSignResponse.getSignedPDF())); + jsonResponse.put(JSON_OUTPUT_SIG, verifyResult.getValueCheckCode().getCode()); + jsonResponse.put(JSON_OUTPUT_CER, verifyResult.getCertificateCheck().getCode()); + + } else { + + PdfAsHelper.setStatisticEvent(request, response, statisticEvent); + PdfAsHelper.setVerificationLevel(request, + VerifyParameter.SignatureVerificationLevel.INTEGRITY_ONLY_VERIFICATION); + + String pdfDataHash = DigestHelper.getHexEncodedHash(inputDocument); + + PdfAsHelper.setSignatureDataHash(request, pdfDataHash); + logger.debug("Storing signatures data hash: " + pdfDataHash); + + logger.debug("Starting signature creation with: " + connector); + + // start asynchronous signature creation + + if (PDFASSignParameters.Connector.BKU.equals(connectorEnum)) { + if (WebConfiguration.getLocalBKUURL() == null) { + throw new PdfAsWebException( + "Invalid connector bku is not supported"); + } + } + + if (PDFASSignParameters.Connector.ONLINEBKU.equals(connectorEnum)) { + if (WebConfiguration.getLocalBKUURL() == null) { + throw new PdfAsWebException( + "Invalid connector onlinebku is not supported"); + } + } + + if (PDFASSignParameters.Connector.MOBILEBKU.equals(connectorEnum)) { + if (WebConfiguration.getLocalBKUURL() == null) { + throw new PdfAsWebException( + "Invalid connector mobilebku is not supported"); + } + } + + + PdfAsHelper.startSignatureJson(request, response, getServletContext(), + inputDocument, connectorEnum.toString(), + position, + null, + profile, null, + null); + + JSONStartResponse jsonStartResponse = PdfAsHelper.startJsonProcess(request, response, getServletContext()); + + if(jsonStartResponse == null) { + throw new PdfAsWebException( + "Invalid configuration for json API"); + } + + jsonResponse.put(JSON_DATAURL, jsonStartResponse.getUrl()); + jsonResponse.put(JSON_BKUURL, jsonStartResponse.getBkuURL()); + jsonResponse.put(JSON_SLREQUEST, jsonStartResponse.getSlRequest()); + } + + response.setContentType("application/json"); + IOUtils.write(jsonResponse.toString(), response.getOutputStream(), "UTF-8"); + + } catch (Throwable e) { + + statisticEvent.setStatus(StatisticEvent.Status.ERROR); + statisticEvent.setException(e); + if(e instanceof PDFASError) { + statisticEvent.setErrorCode(((PDFASError)e).getCode()); + } + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + + logger.warn("Error in JSON Service", e); + if (e.getCause() != null) { + throw new ServletException(e.getCause().getMessage()); + } else { + throw new ServletException(e.getMessage()); + } + } finally { + logger.debug("Done JSON Sign Request"); + } + } +} diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java index 4fce6860..cf8486b5 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java @@ -31,6 +31,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import at.gv.egiz.pdfas.web.config.WebConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -85,6 +86,18 @@ public class PDFData extends HttpServlet { String plainPDFDigest = PdfAsParameterExtractor.getOrigDigest(request); if (signedData != null) { + + if(WebConfiguration.isKeepSignedDocument()) { + if(PdfAsHelper.isSignedDataExpired(request, response)) { + logger.debug("Destroying expired signed data in session : {}", request.getSession().getId()); + request.getSession().invalidate(); + PdfAsHelper.setSessionException(request, response, + "No signed pdf document available.", null); + PdfAsHelper.gotoError(getServletContext(), request, response); + return; + } + } + if (plainPDFDigest != null) { String signatureDataHash = PdfAsHelper .getSignatureDataHash(request); @@ -132,7 +145,12 @@ public class PDFData extends HttpServlet { os.close(); // When data is collected destroy session! - request.getSession().invalidate(); + if(!WebConfiguration.isKeepSignedDocument()) { + logger.debug("Destroying signed data in session : {}", request.getSession().getId()); + request.getSession().invalidate(); + } else { + logger.debug("Keeping signed data in session : {}", request.getSession().getId()); + } } else { PdfAsHelper.setSessionException(request, response, "No signed pdf document available.", null); -- cgit v1.2.3