From bee5dd259a4438d45ecd1bcc26dfba12875236d6 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Tue, 26 Jun 2018 11:03:48 +0200 Subject: initial commit --- .../impl/idp/controller/AbstractController.java | 354 +++++++++++++++++++++ 1 file changed, 354 insertions(+) create mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java (limited to 'eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java') diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java new file mode 100644 index 00000000..980d77ba --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java @@ -0,0 +1,354 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eaaf.core.impl.idp.controller; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +import javax.naming.ConfigurationException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.text.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.web.bind.annotation.ExceptionHandler; + +import at.gv.egiz.components.eventlog.api.EventConstants; +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.IRequestStorage; +import at.gv.egiz.eaaf.core.api.IStatusMessager; +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.data.ExceptionContainer; +import at.gv.egiz.eaaf.core.api.gui.IGUIBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.gui.IGUIBuilderConfigurationFactory; +import at.gv.egiz.eaaf.core.api.gui.IGUIFormBuilder; +import at.gv.egiz.eaaf.core.api.gui.ModifyableGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; +import at.gv.egiz.eaaf.core.api.logging.IStatisticLogger; +import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; +import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.GUIBuildException; +import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; +import at.gv.egiz.eaaf.core.exceptions.ProcessExecutionException; +import at.gv.egiz.eaaf.core.exceptions.ProtocolNotActiveException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.utils.HTTPUtils; +import at.gv.egiz.eaaf.core.impl.utils.Random; +import at.gv.egiz.eaaf.core.impl.utils.ServletUtils; + + +/** + * @author tlenz + * + */ +public abstract class AbstractController { + + private static final Logger log = LoggerFactory.getLogger(AbstractController.class); + + @Autowired(required=true) protected ApplicationContext applicationContext; + @Autowired(required=true) protected IConfiguration authConfig; + @Autowired(required=true) protected ITransactionStorage transactionStorage; + @Autowired(required=true) protected IRequestStorage requestStorage; + @Autowired(required=true) protected IGUIFormBuilder guiBuilder; + @Autowired(required=true) protected IGUIBuilderConfigurationFactory guiConfigFactory; + @Autowired(required=true) protected IStatusMessager statusMessager; + + @Autowired protected IStatisticLogger statisticLogger; + @Autowired protected IRevisionLogger revisionsLogger; + + + + + + @ExceptionHandler({EAAFException.class}) + public void MOAIDExceptionHandler(HttpServletRequest req, HttpServletResponse resp, Exception e) throws IOException { + log.error(e.getMessage() , e); + internalMOAIDExceptionHandler(req, resp, e, true); + + } + + @ExceptionHandler({Exception.class}) + public void GenericExceptionHandler(HttpServletResponse resp, Exception exception) throws IOException { + log.error("Internel Server Error." , exception); + resp.setContentType(EAAFConstants.CONTENTTYPE_HTML_UTF8); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal Server Error!" + + "(Errorcode=9199" + +" | Description=" + + StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(exception.getMessage())) + + ")"); + return; + + } + + @ExceptionHandler({IOException.class}) + public void IOExceptionHandler(HttpServletResponse resp, Throwable exception) { + log.error("Internel Server Error." , exception); + resp.setContentType(EAAFConstants.CONTENTTYPE_HTML_UTF8); + resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + return; + + } + + protected void handleError(String errorMessage, Throwable exceptionThrown, + HttpServletRequest req, HttpServletResponse resp, IRequest pendingReq) throws IOException { + + String pendingRequestID = null; + if (pendingReq != null) + pendingRequestID = pendingReq.getPendingRequestId(); + + Throwable loggedException = null; + Throwable extractedException = extractOriginalExceptionFromProcessException(exceptionThrown); + + //extract pendingRequestID and originalException if it was a TaskExecutionException + if (extractedException instanceof TaskExecutionException) { + //set original exception + loggedException = ((TaskExecutionException) extractedException).getOriginalException(); + + //use TaskExecutionException directly, if no Original Exeception is included + if (loggedException == null) + loggedException = exceptionThrown; + + //set pending-request ID if it is set + String reqID = ((TaskExecutionException) extractedException).getPendingRequestID(); + if (StringUtils.isNotEmpty(reqID)) + pendingRequestID = reqID; + + } else + loggedException = exceptionThrown; + + try { + //switch to protocol-finalize method to generate a protocol-specific error message + + //log error directly in debug mode + if (log.isDebugEnabled()) + log.warn(loggedException.getMessage(), loggedException); + + + //put exception into transaction store for redirect + String key = Random.nextLongRandom(); + if (pendingReq != null) { + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR); + transactionStorage.put(key, + new ExceptionContainer(pendingReq, loggedException), -1); + + } else { + transactionStorage.put(key, + new ExceptionContainer(null, loggedException), -1); + + } + + //build up redirect URL + String redirectURL = null; + redirectURL = ServletUtils.getBaseUrl(req); + redirectURL += "/"+AbstractAuthProtocolModulController.ENDPOINT_ERRORHANDLING + + "?" + EAAFConstants.PARAM_HTTP_ERROR_CODE + "=" + key; + +// //only add pending-request Id if it exists +// if (StringUtils.isNotEmpty(pendingRequestID)) +// redirectURL += "&" + EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID + "=" + pendingRequestID; + + resp.setContentType("text/html"); + resp.setStatus(302); + + resp.addHeader("Location", redirectURL); + log.debug("REDIRECT TO: " + redirectURL); + + return; + + } catch (Exception e) { + log.warn("Default error-handling FAILED. Exception can not be stored ....", e); + log.info("Switch to generic generic backup error-handling ... "); + handleErrorNoRedirect(loggedException, req, resp, true); + + } + + } + + /** + * Handles all exceptions with no pending request. + * Therefore, the error is written to the users browser + * + * @param throwable + * @param req + * @param resp + * @throws IOException + */ + protected void handleErrorNoRedirect(Throwable throwable, HttpServletRequest req, + HttpServletResponse resp, boolean writeExceptionToStatisticLog) throws IOException { + + //log Exception into statistic database + if (writeExceptionToStatisticLog) + statisticLogger.logErrorOperation(throwable); + + //write errror to console + logExceptionToTechnicalLog(throwable); + + //return error to Web browser + if (throwable instanceof EAAFException || throwable instanceof ProcessExecutionException) + internalMOAIDExceptionHandler(req, resp, (Exception)throwable, false); + + else { + //write generic message for general exceptions + String msg = statusMessager.getMessage(IStatusMessager.CODES_INTERNAL_ERROR_GENERIC, null); + writeHTMLErrorResponse(req, resp, msg, "9199", (Exception) throwable); + + } + + } + + /** + * Write a Exception to the MOA-ID-Auth internal technical log + * + * @param loggedException Exception to log + */ + protected void logExceptionToTechnicalLog(Throwable loggedException) { + if (!( loggedException instanceof EAAFException + || loggedException instanceof ProcessExecutionException )) { + log.error("Receive an internal error: Message=" + loggedException.getMessage(), loggedException); + + } else { + if (log.isDebugEnabled() || log.isTraceEnabled()) { + log.warn(loggedException.getMessage(), loggedException); + + } else { + log.warn(loggedException.getMessage()); + + } + } + } + + private void writeBadRequestErrorResponse(HttpServletRequest req, HttpServletResponse resp, EAAFException e) throws IOException { + String code = statusMessager.mapInternalErrorToExternalError(((InvalidProtocolRequestException)e).getErrorId()); + String descr = StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(e.getMessage())); + resp.setContentType(EAAFConstants.CONTENTTYPE_HTML_UTF8); + resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Protocol validation FAILED!" + + "(Errorcode=" + code + + " | Description=" + descr + ")"); + + } + + private void writeHTMLErrorResponse(HttpServletRequest req, HttpServletResponse httpResp, String msg, String errorCode, Exception error) throws IOException { + + try { + IGUIBuilderConfiguration config + = guiConfigFactory.getDefaultErrorGUI(HTTPUtils.extractAuthURLFromRequest(req)); + +// HTTPUtils.extractAuthURLFromRequest(req), +// DefaultGUIFormBuilderConfiguration.VIEW_ERRORMESSAGE, +// null); + + //add errorcode and errormessage + if (config instanceof ModifyableGuiBuilderConfiguration) { + ((ModifyableGuiBuilderConfiguration)config).putCustomParameter("errorMsg", msg); + ((ModifyableGuiBuilderConfiguration)config).putCustomParameter("errorCode", errorCode); + + //add stacktrace if debug is enabled + if (log.isTraceEnabled()) { + ((ModifyableGuiBuilderConfiguration)config).putCustomParameter("stacktrace", getStacktraceFromException(error)); + + } + + } else + log.info("Can not ADD error message, because 'GUIBuilderConfiguration' is not modifieable "); + + + + guiBuilder.build(httpResp, config, "Error-Message"); + + } catch (GUIBuildException e) { + log.warn("Can not build error-message GUI.", e); + GenericExceptionHandler(httpResp, e); + + } + + } + + private void writeHTMLErrorResponse(HttpServletRequest req, HttpServletResponse httpResp, Exception error) throws IOException { + writeHTMLErrorResponse(req, httpResp, + error.getMessage(), + statusMessager.getResponseErrorCode(error), + error); + } + + + private String getStacktraceFromException(Exception ex) { + StringWriter errors = new StringWriter(); + ex.printStackTrace(new PrintWriter(errors)); + return errors.toString(); + + } + + /** + * Extracts a TaskExecutionException of a ProcessExecutionExeception Stacktrace. + * + * @param exception + * @return Return the latest TaskExecutionExecption if exists, otherwise the latest ProcessExecutionException + */ + private Throwable extractOriginalExceptionFromProcessException(Throwable exception) { + Throwable exholder = exception; + TaskExecutionException taskExc = null; + + while(exholder != null + && exholder instanceof ProcessExecutionException) { + ProcessExecutionException procExc = (ProcessExecutionException) exholder; + if (procExc.getCause() != null && + procExc.getCause() instanceof TaskExecutionException) { + taskExc = (TaskExecutionException) procExc.getCause(); + exholder = taskExc.getOriginalException(); + + } else + break; + + } + + if (taskExc == null) + return exholder; + + else + return taskExc; + } + + private void internalMOAIDExceptionHandler(HttpServletRequest req, HttpServletResponse resp, Exception e, boolean writeExceptionToStatisicLog) throws IOException { + if (e instanceof ProtocolNotActiveException) { + resp.getWriter().write(e.getMessage()); + resp.setContentType(EAAFConstants.CONTENTTYPE_HTML_UTF8); + resp.sendError(HttpServletResponse.SC_FORBIDDEN, + StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(e.getMessage()))); + + } else if (e instanceof AuthnRequestValidatorException) { + AuthnRequestValidatorException ex = (AuthnRequestValidatorException)e; + //log Error Message + if (writeExceptionToStatisicLog) + statisticLogger.logErrorOperation(ex, ex.getErrorRequest()); + + //write error message + writeBadRequestErrorResponse(req, resp, (EAAFException) e); + + } else if (e instanceof InvalidProtocolRequestException) { + //send error response + writeBadRequestErrorResponse(req, resp, (EAAFException) e); + + } else if (e instanceof ConfigurationException) { + //send HTML formated error message + writeHTMLErrorResponse(req, resp, (EAAFException) e); + + } else if (e instanceof EAAFException) { + //send HTML formated error message + writeHTMLErrorResponse(req, resp, e); + + } else if (e instanceof ProcessExecutionException) { + //send HTML formated error message + writeHTMLErrorResponse(req, resp, e); + + } + + } + +} -- cgit v1.2.3