All Downloads are FREE. Search and download functionalities are using the official Maven repository.

se.idsec.signservice.integration.process.impl.DefaultSignResponseProcessor Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2019-2023 IDsec Solutions AB
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package se.idsec.signservice.integration.process.impl;

import jakarta.annotation.Nonnull;
import jakarta.annotation.PostConstruct;
import jakarta.xml.bind.JAXBException;
import lombok.extern.slf4j.Slf4j;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import se.idsec.signservice.dss.DSSStatusCodes;
import se.idsec.signservice.integration.SignResponseCancelStatusException;
import se.idsec.signservice.integration.SignResponseErrorStatusException;
import se.idsec.signservice.integration.SignResponseProcessingParameters;
import se.idsec.signservice.integration.SignatureResult;
import se.idsec.signservice.integration.SignatureResult.SignatureResultBuilder;
import se.idsec.signservice.integration.authentication.SignerAssertionInformation;
import se.idsec.signservice.integration.config.IntegrationServiceConfiguration;
import se.idsec.signservice.integration.core.error.ErrorCode;
import se.idsec.signservice.integration.core.error.SignServiceIntegrationException;
import se.idsec.signservice.integration.core.error.impl.InternalSignServiceIntegrationException;
import se.idsec.signservice.integration.core.error.impl.SignServiceProtocolException;
import se.idsec.signservice.integration.core.impl.CorrelationID;
import se.idsec.signservice.integration.document.CompiledSignedDocument;
import se.idsec.signservice.integration.document.SignedDocument;
import se.idsec.signservice.integration.document.SignedDocumentProcessor;
import se.idsec.signservice.integration.document.TbsDocument;
import se.idsec.signservice.integration.document.ades.AdesObject;
import se.idsec.signservice.integration.dss.DssUtils;
import se.idsec.signservice.integration.dss.SignRequestWrapper;
import se.idsec.signservice.integration.dss.SignResponseWrapper;
import se.idsec.signservice.integration.process.SignResponseProcessingConfig;
import se.idsec.signservice.integration.process.SignResponseProcessor;
import se.idsec.signservice.integration.state.SignatureSessionState;
import se.idsec.signservice.security.certificate.CertificateUtils;
import se.idsec.signservice.security.certificate.CertificateValidator;
import se.idsec.signservice.security.certificate.impl.SimpleCertificateValidator;
import se.idsec.signservice.security.sign.xml.XMLMessageSignatureValidator;
import se.idsec.signservice.security.sign.xml.XMLSignatureLocation;
import se.idsec.signservice.security.sign.xml.XMLSignatureLocation.ChildPosition;
import se.idsec.signservice.security.sign.xml.impl.DefaultXMLMessageSignatureValidator;
import se.idsec.signservice.utils.AssertThat;
import se.idsec.signservice.utils.ProtocolVersion;
import se.idsec.signservice.xml.DOMUtils;
import se.swedenconnect.schemas.csig.dssext_1_1.SignResponseExtension;
import se.swedenconnect.schemas.csig.dssext_1_1.SignTaskData;
import se.swedenconnect.schemas.csig.dssext_1_1.SignTasks;
import se.swedenconnect.schemas.csig.dssext_1_1.SignatureCertificateChain;
import se.swedenconnect.schemas.dss_1_0.SignResponse;
import se.swedenconnect.xml.jaxb.JAXBUnmarshaller;

import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.xpath.XPathExpressionException;
import java.security.GeneralSecurityException;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * Default implementation of the {@link SignResponseProcessor} interface.
 *
 * @author Martin Lindström ([email protected])
 * @author Stefan Santesson ([email protected])
 */
@Slf4j
public class DefaultSignResponseProcessor implements SignResponseProcessor {

  /** The version to assume if no version has been set. */
  private final static ProtocolVersion DEFAULT_VERSION = ProtocolVersion.valueOf("1.1");

  /** For validating signatures on SignResponse messages. */
  private final XMLMessageSignatureValidator signResponseSignatureValidator = new DefaultXMLMessageSignatureValidator();

  /** Needed when validating the SignResponse signatures. */
  private final XMLSignatureLocation xmlSignatureLocation;

  /** The processors for handling the signed documents. */
  private List> signedDocumentProcessors;

  /** Processor for handling the signer assertion info. */
  private SignerAssertionInfoProcessor signerAssertionInfoProcessor;

  /** Processing config. */
  private SignResponseProcessingConfig processingConfiguration;

  /**
   * An optional mapping between policies and certificate validators. It does not matter what trust anchor each
   * validator has been configured with since this will be explicitly set for each call. This information is taken from
   * the {@link IntegrationServiceConfiguration#getTrustAnchors()}.
   * 

* If no mapping for a given policy exists, a default validator will be used (see * {@link SimpleCertificateValidator}). *

*/ private Map certificateValidators; /** The default certificate validator. This instance is used if no explicit mapping exists. */ private final CertificateValidator defaultCertificateValidator = new SimpleCertificateValidator(); /** * Constructor. */ public DefaultSignResponseProcessor() { try { this.xmlSignatureLocation = new XMLSignatureLocation("/*/*[local-name()='OptionalOutputs']", ChildPosition.LAST); } catch (final XPathExpressionException e) { log.error("Failed to setup XPath for signature validation", e); throw new SecurityException("Failed to setup XPath for signature validation", e); } } /** {@inheritDoc} */ @Nonnull @Override public SignatureResult processSignResponse(@Nonnull final String signResponse, @Nonnull final SignatureSessionState sessionState, @Nonnull final IntegrationServiceConfiguration config, final SignResponseProcessingParameters parameters) throws SignResponseErrorStatusException, SignServiceIntegrationException { // First decode the encoded SignResponse ... // final Document signResponseDocument; final SignResponseWrapper response; try { signResponseDocument = DOMUtils.base64ToDocument(signResponse); if (log.isTraceEnabled()) { log.trace("{}: SignResponse: {}", CorrelationID.id(), DOMUtils.prettyPrint(signResponseDocument)); } response = new SignResponseWrapper(JAXBUnmarshaller.unmarshall(signResponseDocument, SignResponse.class)); // Make sure we can process this response ... if (!DssUtils.DSS_PROFILE.equals(response.getProfile())) { final String msg = String.format("Invalid SignResponse (RequestID: %s) - Expected Profile='%s' but was '%s'", response.getRequestID(), DssUtils.DSS_PROFILE, response.getProfile()); log.error("{}: {}", CorrelationID.id(), msg); throw new SignServiceProtocolException(msg); } } catch (final DOMException | JAXBException e) { throw new SignServiceProtocolException("Failed to decode received SignResponse", e); } // Validate the signature of the SignResponse ... // try { this.signResponseSignatureValidator.validate(signResponseDocument, config.getSignServiceCertificatesInternal(), this.xmlSignatureLocation); } catch (final SignatureException e) { final String msg = String.format("Failed to verify signature on SignResponse - %s", e.getMessage()); log.error("{}: {}", CorrelationID.id(), msg, e); throw new SignResponseProcessingException(new ErrorCode.Code("signature"), msg, e); } // Make sure that the received message is in response to the passed request. // if (!sessionState.getSignRequest().getRequestID().equals(response.getRequestID())) { final String msg = String.format("RequestID in SignResponse '%s' does not match expected RequestID '%s'", response.getRequestID(), sessionState.getSignRequest().getRequestID()); log.error("{}: {}", CorrelationID.id(), msg); throw new SignResponseProcessingException(new ErrorCode.Code("mismatch-id"), msg); } // Check result ... // if (response.getResult() == null) { final String msg = "Received SignResponse is missing Result element"; log.error("{}: {}", CorrelationID.id(), msg); throw new SignServiceProtocolException(msg); } if (!DSSStatusCodes.DSS_SUCCESS.equals(response.getResult().getResultMajor())) { log.info("{}: SignResponse with ID '{}' reported error: '{}' - '{}' - '{}'", CorrelationID.id(), response.getRequestID(), response.getResult().getResultMajor(), response.getResult().getResultMinor(), response.getResult().getResultMessage() != null ? response.getResult().getResultMessage().getValue() : "-"); if (DSSStatusCodes.DSS_MINOR_USER_CANCEL.equals(response.getResult().getResultMinor())) { throw new SignResponseCancelStatusException(); } throw new SignResponseErrorStatusException(response.getResult().getResultMajor(), response.getResult().getResultMinor(), response.getResult().getResultMessage() != null ? response.getResult().getResultMessage().getValue() : null); } // Check version of response ... // final ProtocolVersion requestVersion = Optional.ofNullable(sessionState.getSignRequest().getSignRequestExtension().getVersion()) .map(ProtocolVersion::valueOf) .orElse(DEFAULT_VERSION); final ProtocolVersion responseVersion = Optional.ofNullable(response.getSignResponseExtension().getVersion()) .map(ProtocolVersion::valueOf) .orElse(DEFAULT_VERSION); if (!requestVersion.equals(responseVersion)) { // OK, this is an error. The response version MUST be set to the same version as the request version ... final String msg = String.format("Version of SignResponse (%s) does not equal version of SignRequest (%s)", responseVersion, requestVersion); log.error("{}: {}", CorrelationID.id(), msg); throw new SignResponseProcessingException(new ErrorCode.Code("version"), msg); } // OK, it's a success. // // Next, validate the response ... // final SignatureResultBuilder resultBuilder = SignatureResult.builder(); resultBuilder .id(sessionState.getSignRequest().getRequestID()) .correlationId(CorrelationID.id()); final SignResponseExtension signResponseExtension = response.getSignResponseExtension(); if (signResponseExtension == null) { final String msg = String.format("SignResponse does not contain SignResponseExtension [request-id='%s']", sessionState.getSignRequest().getRequestID()); log.error("{}: {}", CorrelationID.id(), msg); throw new SignServiceProtocolException(msg); } // Verify that the response is not too old ... // this.validateResponseTime(signResponseExtension.getResponseTime(), sessionState.getSignRequest().getSignRequestExtension().getRequestTime(), sessionState.getSignRequest().getRequestID()); // Make sure that the request bytes are there (1.1 only) ... // if (responseVersion.compareTo("1.1") <= 0) { this.validateReceivedRequest(signResponseExtension.getRequest(), sessionState.getSignRequest()); } // Get hold of the signer certificate chain ... // final List signerCertificateChain = this.getSignerCertificateChain(signResponseExtension .getSignatureCertificateChain(), sessionState.getSignRequest().getRequestID()); // Let's validate the signer certificate // final CertificateValidator certificateValidator = this.getCertificateValidator(config.getPolicy()); try { certificateValidator.validate(signerCertificateChain.get(0), signerCertificateChain.size() > 1 ? signerCertificateChain.subList(1, signerCertificateChain.size()) : null, null, config.getTrustAnchorsInternal()); log.info("{}: Signer certificate successfully validated - {} [request-id='{}']", CorrelationID.id(), CertificateUtils.toLogString(signerCertificateChain.get(0)), sessionState.getSignRequest().getRequestID()); } catch (final GeneralSecurityException e) { final String msg = String.format("Validation of signer certificate failed - %s [request-id='%s']", e.getMessage(), sessionState.getSignRequest().getRequestID()); log.error("{}: {}", CorrelationID.id(), msg); throw new SignResponseProcessingException(new ErrorCode.Code("invalid-signercert"), msg, e); } // If we are using strict processing we assert that the user certificate contains what we expect ... // if (this.processingConfiguration.isStrictProcessing()) { // TODO: Validate that the user certificate looks ok ... } // Get the signer assertion information (and validate it). // final SignerAssertionInformation signerAssertionInformation = this.signerAssertionInfoProcessor.processSignerAssertionInfo(response, sessionState, parameters); resultBuilder.signerAssertionInformation(signerAssertionInformation); // Make sure that we got a sign task data for each TBS document ... // final SignTasks signTasks = response.getSignTasks(); if (signTasks.getSignTaskDatas().size() != sessionState.getTbsDocuments().size()) { final String msg = String.format("SignResponse contains %d signatures, but %d was requested [request-id='%s']", signTasks.getSignTaskDatas().size(), sessionState.getTbsDocuments().size(), sessionState.getSignRequest().getRequestID()); log.error("{}: {}", CorrelationID.id(), msg); throw new SignResponseProcessingException(new ErrorCode.Code("invalid-response"), msg); } // Now, iterate over all signatures and build signed documents and validate them ... // for (final SignTaskData signTaskData : signTasks.getSignTaskDatas()) { // Make sure the SignTaskData follows the specs and holds all required fields ... this.checkSignTaskData(signTaskData, sessionState.getSignRequest()); // Find a processor for this object ... final SignedDocumentProcessor processor = this.signedDocumentProcessors.stream() .filter(p -> p.supports(signTaskData)) .findFirst() .orElseThrow(() -> new InternalSignServiceIntegrationException(new ErrorCode.Code("config"), "Could not find document processor")); // Process the document ... final SignedDocument signedDocument = this.processDocument(processor, signTaskData, signerCertificateChain, sessionState, response, parameters); // Add it to the result ... resultBuilder.signedDocument(signedDocument); } return resultBuilder.build(); } /** * Compiles a signed document and validates it. * * @param processor the document processor * @param signTaskData the sign task data * @param signerCertificateChain the certificate chain * @param state the session state * @param signResponse the sign response * @param parameters optional processing parameters * @return a signed document * @throws SignServiceIntegrationException for processing errors */ protected SignedDocument processDocument(final SignedDocumentProcessor processor, final SignTaskData signTaskData, final List signerCertificateChain, final SignatureSessionState state, final SignResponseWrapper signResponse, final SignResponseProcessingParameters parameters) throws SignServiceIntegrationException { // Find a corresponding TbsDocument ... final TbsDocument tbsDocument = this.getTbsDocument(signTaskData, state); // Build the signed document ... final CompiledSignedDocument signedDocument = processor.buildSignedDocument(tbsDocument, signTaskData, signerCertificateChain, state.getSignRequest(), parameters); // Validate the signature of the document ... processor.validateSignedDocument( signedDocument.getDocument(), signerCertificateChain.get(0), signTaskData, parameters, state.getSignRequest().getRequestID()); // Optionally, validate the XAdES object ... if (signedDocument.getAdesObject() != null) { processor.validateAdesObject(signedDocument.getAdesObject(), signerCertificateChain.get(0), signTaskData, state.getSignRequest(), signResponse, parameters); } return signedDocument.getSignedDocument(); } /** * Validates the response time from the SignResponse is valid. The method also ensures that the server processing time * hasn't exceeded or max limit. * * @param responseTime the response time * @param requestTime the time when the request was sent * @param requestID the requestID (for logging) * @throws SignServiceIntegrationException for expired responses */ protected void validateResponseTime(final XMLGregorianCalendar responseTime, final XMLGregorianCalendar requestTime, final String requestID) throws SignServiceIntegrationException { if (responseTime == null) { final String msg = String.format("SignResponse does not contain required ResponseTime [request-id='%s']", requestID); log.error("{}: {}", CorrelationID.id(), msg); throw new SignServiceProtocolException(msg); } final long responseTimeMillis = responseTime.toGregorianCalendar().getTimeInMillis(); final long now = System.currentTimeMillis(); // Has the response expired? // if (now - responseTimeMillis - this.processingConfiguration.getAllowedClockSkew() > this.processingConfiguration .getMaximumAllowedResponseAge()) { final String msg = String.format( "SignResponse is too old. response-time:%d - current-time:%d - max-allowed-age:%d - " + "allowed-clock-skew:%d [request-id='%s']", responseTimeMillis, now, this.processingConfiguration.getMaximumAllowedResponseAge(), this.processingConfiguration.getAllowedClockSkew(), requestID); log.error("{}: {}", CorrelationID.id(), msg); throw new SignResponseProcessingException(new ErrorCode.Code("expired-response"), msg); } // Also check the "not yet valid" case... // if (responseTimeMillis - this.processingConfiguration.getAllowedClockSkew() > now) { final String msg = String.format( "SignResponse is not yet valid according to ResponseTime. response-time:%d - current-time:%d - " + "allowed-clock-skew:%d [request-id='%s']", responseTimeMillis, now, this.processingConfiguration.getAllowedClockSkew(), requestID); log.error("{}: {}", CorrelationID.id(), msg); throw new SignResponseProcessingException(new ErrorCode.Code("invalid-response"), msg); } // We also want to ensure that the server processing time hasn't exceeded or max limit ... // We don't have to care about clock skew since we were the ones that set the request time. // final long requestTimeMillis = requestTime.toGregorianCalendar().getTimeInMillis(); if (now - requestTimeMillis > this.processingConfiguration.getMaximumAllowedProcessingTime()) { final String msg = String.format( "Server processing time exceeded allowed limit. request-time:%d - current-time:%d - limit:%d [request-id='%s']", requestTimeMillis, now, this.processingConfiguration.getMaximumAllowedProcessingTime(), requestID); log.error("{}: {}", CorrelationID.id(), msg); throw new SignResponseProcessingException(new ErrorCode.Code("server-processing-time-exceeded-limit"), msg); } } /** * Validates the received Request element (throws only if strict processing is active). * * @param request the received Request element * @param sentRequest the request that was actually sent * @throws SignServiceIntegrationException if the Request is not present or differs from what was sent */ protected void validateReceivedRequest(final byte[] request, final SignRequestWrapper sentRequest) throws SignServiceIntegrationException { if (request == null || request.length == 0) { final String msg = String .format("SignResponse does not contain a Request element - this is required [request-id='%s']", sentRequest .getRequestID()); if (this.processingConfiguration.isStrictProcessing()) { log.error("{}: {}", CorrelationID.id(), msg); throw new SignServiceProtocolException(msg); } log.warn("{}: {}", CorrelationID.id(), msg); } // TODO: If strict processing is active compare this request with our request from the session state. } /** * Gets a list of {@link X509Certificate} by reading the supplied {@code SignatureCertificateChain}. * * @param signatureCertificateChain the chain received in the response * @param requestID the request ID for the response * @return a list of X509Certificate objects * @throws SignServiceIntegrationException for decoding errors */ protected List getSignerCertificateChain( final SignatureCertificateChain signatureCertificateChain, final String requestID) throws SignServiceIntegrationException { // First check that the response contains the signer certificate and the chain ... // if (signatureCertificateChain == null || !signatureCertificateChain.isSetX509Certificates()) { final String msg = String.format("Missing signer certificate chain from SignResponse [request-id='%s']", requestID); log.error("{}: {}", CorrelationID.id(), msg); throw new SignServiceProtocolException(msg); } // Next, decode all certificates ... // final List certificates = new ArrayList<>(); for (final byte[] enc : signatureCertificateChain.getX509Certificates()) { try { certificates.add(CertificateUtils.decodeCertificate(enc)); } catch (final CertificateException e) { final String msg = String.format("Failed to decode certificate in SignatureCertificateChain of SignResponse [request-id='%s']", requestID); log.error("{}: {}", CorrelationID.id(), msg); throw new SignResponseProcessingException(new ErrorCode.Code("invalid-response"), msg); } } return certificates; } /** * Make checks that the supplied {@code SignTaskData} object follows the specs. * * @param signTaskData the object to check * @param signRequest the sign request corresponding to the response in which we received the SignTaskData * @throws SignServiceIntegrationException for validation errors */ protected void checkSignTaskData(final SignTaskData signTaskData, final SignRequestWrapper signRequest) throws SignServiceIntegrationException { // Make sure we have a Task-ID ... // if (signTaskData.getSignTaskId() == null) { final String msg = String.format("Missing SignTaskId for signed document [request-id='%s']", signRequest.getRequestID()); log.error("{}: {}", CorrelationID.id(), msg); throw new SignServiceProtocolException(msg); } // Type is required ... // if (signTaskData.getSigType() == null) { final String msg = String.format("Missing SigType for signed document with ID '%s' [request-id='%s']", signTaskData.getSignTaskId(), signRequest.getRequestID()); log.error("{}: {}", CorrelationID.id(), msg); throw new SignServiceProtocolException(msg); } // The ToBeSignedBytes are required ... // if (signTaskData.getToBeSignedBytes() == null || signTaskData.getToBeSignedBytes().length == 0) { final String msg = String.format("Missing ToBeSignedBytes for signed document with ID '%s' [request-id='%s']", signTaskData.getSignTaskId(), signRequest.getRequestID()); log.error("{}: {}", CorrelationID.id(), msg); throw new SignServiceProtocolException(msg); } // Make checks about the signature ... // if (signTaskData.getBase64Signature() == null || signTaskData.getBase64Signature().getValue() == null || signTaskData.getBase64Signature().getValue().length == 0) { final String msg = String.format("Sign task '%s' is missing signature [request-id='%s']", signTaskData.getSignTaskId(), signRequest.getRequestID()); log.error("{}: {}", CorrelationID.id(), msg); throw new SignServiceProtocolException(msg); } if (signTaskData.getBase64Signature().getType() != null) { if (!signTaskData.getBase64Signature() .getType() .equals( signRequest.getSignRequestExtension().getRequestedSignatureAlgorithm())) { final String msg = String.format( "Signature algorithm used for sign task '%s' (%s) does not match requested signature '%s' [request-id='%s']", signTaskData.getSignTaskId(), signTaskData.getBase64Signature().getType(), signRequest.getSignRequestExtension().getRequestedSignatureAlgorithm(), signRequest.getRequestID()); log.error("{}: {}", CorrelationID.id(), msg); throw new SignResponseProcessingException(new ErrorCode.Code("invalid-response"), msg); } } } /** * Given a {@code SignTaskData} the method finds the corresponding TBS document from the session state. * * @param signTaskData the signature * @param state the state holding the TBS documents * @return a TbsDocument * @throws SignServiceIntegrationException if no matching TBS document is found */ protected TbsDocument getTbsDocument(final SignTaskData signTaskData, final SignatureSessionState state) throws SignServiceIntegrationException { // Locate the matching TBS document from the session state ... // final TbsDocument tbsDocument = state.getTbsDocuments() .stream() .filter(d -> d.getId().equals(signTaskData.getSignTaskId())) .findFirst() .orElse(null); if (tbsDocument == null) { final String msg = String.format( "SignResponse contains SignTask with ID '%s' - This ID does not appear in SignRequest [request-id='%s']", signTaskData.getSignTaskId(), state.getSignRequest().getRequestID()); log.error("{}: {}", CorrelationID.id(), msg); throw new SignResponseProcessingException(new ErrorCode.Code("invalid-response"), msg); } return tbsDocument; } /** * Gets a certificate validator that is to be used to perform a certificate validation according to the supplied * policy. * * @param policy the policy * @return a certificate validator */ private CertificateValidator getCertificateValidator(final String policy) { final CertificateValidator validator = this.certificateValidators != null ? this.certificateValidators.get(policy) : null; return validator != null ? validator : this.defaultCertificateValidator; } /** * Assigns the processors for handling the signed documents. * * @param signedDocumentProcessors document processors */ public void setSignedDocumentProcessors(final List> signedDocumentProcessors) { this.signedDocumentProcessors = signedDocumentProcessors; } /** * Assigns the processor for handling the signer assertion info from the sign response. If not assigned an instance of * {@link DefaultSignerAssertionInfoProcessor} will be used. * * @param signerAssertionInfoProcessor signer assertion info processor */ public void setSignerAssertionInfoProcessor(final SignerAssertionInfoProcessor signerAssertionInfoProcessor) { this.signerAssertionInfoProcessor = signerAssertionInfoProcessor; } /** * Assigns the processing config settings. * * @param processingConfiguration the processing config settings */ public void setProcessingConfiguration(final SignResponseProcessingConfig processingConfiguration) { this.processingConfiguration = processingConfiguration; } /** {@inheritDoc} */ @Nonnull @Override public SignResponseProcessingConfig getProcessingConfiguration() { return this.processingConfiguration; } /** * Assigns a mapping between policies and certificate validators. It does not matter what trust anchor each validator * has been configured with since this will be explicitly set for each call. This information is taken from the * {@link IntegrationServiceConfiguration#getTrustAnchors()}. *

* If no mapping for a given policy exists, a default validator will be used (see * {@link SimpleCertificateValidator}). *

* * @param certificateValidators policy to certificate validator mappings */ public void setCertificateValidators(final Map certificateValidators) { this.certificateValidators = certificateValidators; } /** * Ensures that all required properties have been assigned. The method also makes sure that the * {@code processingConfiguration} property is assigned (by default * {@link SignResponseProcessingConfig#defaultSignResponseProcessingConfig()} is used) and that * {@code signerAssertionInfoProcessor} is set (by default a {@link DefaultSignerAssertionInfoProcessor} is used). * *

* Note: If executing in a Spring Framework environment this method is automatically invoked after all properties have * been assigned. Otherwise it should be explicitly invoked. *

* * @throws Exception if not all settings are correct */ @PostConstruct public void afterPropertiesSet() throws Exception { AssertThat.isNotEmpty(this.signedDocumentProcessors, "At least one document processor must be configured"); if (this.processingConfiguration == null) { this.processingConfiguration = SignResponseProcessingConfig.defaultSignResponseProcessingConfig(); } if (this.signerAssertionInfoProcessor == null) { final DefaultSignerAssertionInfoProcessor p = new DefaultSignerAssertionInfoProcessor(); p.setProcessingConfig(this.processingConfiguration); this.signerAssertionInfoProcessor = p; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy