KEYCLOAK-4148 Prevent unnecessary deserialization when supported
... and gain another ~ 5-10 %
This commit is contained in:
parent
862502f3ed
commit
ad9210a7a7
5 changed files with 86 additions and 29 deletions
|
@ -33,6 +33,9 @@ import javax.xml.stream.events.Characters;
|
||||||
import javax.xml.stream.events.XMLEvent;
|
import javax.xml.stream.events.XMLEvent;
|
||||||
import javax.xml.stream.util.EventReaderDelegate;
|
import javax.xml.stream.util.EventReaderDelegate;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import javax.xml.transform.Source;
|
||||||
|
import javax.xml.transform.dom.DOMSource;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for parsers
|
* Base class for parsers
|
||||||
|
@ -49,14 +52,13 @@ public abstract class AbstractParser implements ParserNamespaceSupport {
|
||||||
protected XMLInputFactory initialValue() {
|
protected XMLInputFactory initialValue() {
|
||||||
return getXMLInputFactory();
|
return getXMLInputFactory();
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the JAXP {@link XMLInputFactory}
|
* Get the JAXP {@link XMLInputFactory}
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private static XMLInputFactory getXMLInputFactory() {
|
private XMLInputFactory getXMLInputFactory() {
|
||||||
boolean tccl_jaxp = SystemPropertiesUtil.getSystemProperty(GeneralConstants.TCCL_JAXP, "false")
|
boolean tccl_jaxp = SystemPropertiesUtil.getSystemProperty(GeneralConstants.TCCL_JAXP, "false")
|
||||||
.equalsIgnoreCase("true");
|
.equalsIgnoreCase("true");
|
||||||
ClassLoader prevTCCL = SecurityActions.getTCCL();
|
ClassLoader prevTCCL = SecurityActions.getTCCL();
|
||||||
|
@ -71,6 +73,7 @@ public abstract class AbstractParser implements ParserNamespaceSupport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse an InputStream for payload
|
* Parse an InputStream for payload
|
||||||
|
@ -87,6 +90,15 @@ public abstract class AbstractParser implements ParserNamespaceSupport {
|
||||||
return parse(xmlEventReader);
|
return parse(xmlEventReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object parse(Source source) throws ParsingException {
|
||||||
|
XMLEventReader xmlEventReader = createEventReader(source);
|
||||||
|
return parse(xmlEventReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object parse(Node node) throws ParsingException {
|
||||||
|
return parse(new DOMSource(node));
|
||||||
|
}
|
||||||
|
|
||||||
public XMLEventReader createEventReader(InputStream configStream) throws ParsingException {
|
public XMLEventReader createEventReader(InputStream configStream) throws ParsingException {
|
||||||
if (configStream == null)
|
if (configStream == null)
|
||||||
throw logger.nullArgumentError("InputStream");
|
throw logger.nullArgumentError("InputStream");
|
||||||
|
@ -102,6 +114,21 @@ public abstract class AbstractParser implements ParserNamespaceSupport {
|
||||||
return xmlEventReader;
|
return xmlEventReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public XMLEventReader createEventReader(Source source) throws ParsingException {
|
||||||
|
if (source == null)
|
||||||
|
throw logger.nullArgumentError("Source");
|
||||||
|
|
||||||
|
XMLEventReader xmlEventReader = StaxParserUtil.getXMLEventReader(source);
|
||||||
|
|
||||||
|
try {
|
||||||
|
xmlEventReader = filterWhitespaces(xmlEventReader);
|
||||||
|
} catch (XMLStreamException e) {
|
||||||
|
throw logger.parserException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return xmlEventReader;
|
||||||
|
}
|
||||||
|
|
||||||
protected XMLEventReader filterWhitespaces(XMLEventReader xmlEventReader) throws XMLStreamException {
|
protected XMLEventReader filterWhitespaces(XMLEventReader xmlEventReader) throws XMLStreamException {
|
||||||
XMLInputFactory xmlInputFactory = XML_INPUT_FACTORY.get();
|
XMLInputFactory xmlInputFactory = XML_INPUT_FACTORY.get();
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@ import org.keycloak.saml.common.constants.JBossSAMLConstants;
|
||||||
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
|
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
|
||||||
import org.keycloak.saml.common.exceptions.ConfigurationException;
|
import org.keycloak.saml.common.exceptions.ConfigurationException;
|
||||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||||
|
import org.keycloak.saml.common.exceptions.ProcessingException;
|
||||||
|
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
@ -47,6 +49,7 @@ import javax.xml.validation.Schema;
|
||||||
import javax.xml.validation.SchemaFactory;
|
import javax.xml.validation.SchemaFactory;
|
||||||
import javax.xml.validation.Validator;
|
import javax.xml.validation.Validator;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility for the stax based parser
|
* Utility for the stax based parser
|
||||||
|
@ -250,6 +253,34 @@ public class StaxParserUtil {
|
||||||
return xmlEventReader;
|
return xmlEventReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static AtomicBoolean XML_EVENT_READER_ON_SOURCE_SUPPORTED = new AtomicBoolean(true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the XML event reader
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static XMLEventReader getXMLEventReader(Source source) {
|
||||||
|
XMLInputFactory xmlInputFactory = XML_INPUT_FACTORY.get();
|
||||||
|
try {
|
||||||
|
if (XML_EVENT_READER_ON_SOURCE_SUPPORTED.get()) {
|
||||||
|
try {
|
||||||
|
// The following method is optional per specification
|
||||||
|
return xmlInputFactory.createXMLEventReader(source);
|
||||||
|
} catch (UnsupportedOperationException ex) {
|
||||||
|
XML_EVENT_READER_ON_SOURCE_SUPPORTED.set(false);
|
||||||
|
return getXMLEventReader(source);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return getXMLEventReader(DocumentUtil.getSourceAsStream(source));
|
||||||
|
}
|
||||||
|
} catch (ConfigurationException | ProcessingException | XMLStreamException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a {@code Location}, return a formatted string [lineNum,colNum]
|
* Given a {@code Location}, return a formatted string [lineNum,colNum]
|
||||||
*
|
*
|
||||||
|
|
|
@ -165,7 +165,7 @@ public class SAML2Request {
|
||||||
|
|
||||||
SAMLParser samlParser = new SAMLParser();
|
SAMLParser samlParser = new SAMLParser();
|
||||||
JAXPValidationUtil.checkSchemaValidation(samlDocument);
|
JAXPValidationUtil.checkSchemaValidation(samlDocument);
|
||||||
SAML2Object requestType = (SAML2Object) samlParser.parse(DocumentUtil.getNodeAsStream(samlDocument));
|
SAML2Object requestType = (SAML2Object) samlParser.parse(samlDocument);
|
||||||
|
|
||||||
samlDocumentHolder = new SAMLDocumentHolder(requestType, samlDocument);
|
samlDocumentHolder = new SAMLDocumentHolder(requestType, samlDocument);
|
||||||
return requestType;
|
return requestType;
|
||||||
|
@ -192,7 +192,7 @@ public class SAML2Request {
|
||||||
|
|
||||||
SAMLParser samlParser = new SAMLParser();
|
SAMLParser samlParser = new SAMLParser();
|
||||||
JAXPValidationUtil.checkSchemaValidation(samlDocument);
|
JAXPValidationUtil.checkSchemaValidation(samlDocument);
|
||||||
RequestAbstractType requestType = (RequestAbstractType) samlParser.parse(DocumentUtil.getNodeAsStream(samlDocument));
|
RequestAbstractType requestType = (RequestAbstractType) samlParser.parse(samlDocument);
|
||||||
|
|
||||||
samlDocumentHolder = new SAMLDocumentHolder(requestType, samlDocument);
|
samlDocumentHolder = new SAMLDocumentHolder(requestType, samlDocument);
|
||||||
return requestType;
|
return requestType;
|
||||||
|
@ -220,7 +220,7 @@ public class SAML2Request {
|
||||||
SAMLParser samlParser = new SAMLParser();
|
SAMLParser samlParser = new SAMLParser();
|
||||||
JAXPValidationUtil.checkSchemaValidation(samlDocument);
|
JAXPValidationUtil.checkSchemaValidation(samlDocument);
|
||||||
|
|
||||||
AuthnRequestType requestType = (AuthnRequestType) samlParser.parse(DocumentUtil.getNodeAsStream(samlDocument));
|
AuthnRequestType requestType = (AuthnRequestType) samlParser.parse(samlDocument);
|
||||||
samlDocumentHolder = new SAMLDocumentHolder(requestType, samlDocument);
|
samlDocumentHolder = new SAMLDocumentHolder(requestType, samlDocument);
|
||||||
return requestType;
|
return requestType;
|
||||||
}
|
}
|
||||||
|
|
|
@ -376,7 +376,7 @@ public class SAML2Response {
|
||||||
SAMLParser samlParser = new SAMLParser();
|
SAMLParser samlParser = new SAMLParser();
|
||||||
JAXPValidationUtil.checkSchemaValidation(samlDocument);
|
JAXPValidationUtil.checkSchemaValidation(samlDocument);
|
||||||
|
|
||||||
return (EncryptedAssertionType) samlParser.parse(DocumentUtil.getNodeAsStream(samlDocument));
|
return (EncryptedAssertionType) samlParser.parse(samlDocument);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,7 +398,7 @@ public class SAML2Response {
|
||||||
|
|
||||||
SAMLParser samlParser = new SAMLParser();
|
SAMLParser samlParser = new SAMLParser();
|
||||||
JAXPValidationUtil.checkSchemaValidation(samlDocument);
|
JAXPValidationUtil.checkSchemaValidation(samlDocument);
|
||||||
return (AssertionType) samlParser.parse(DocumentUtil.getNodeAsStream(samlDocument));
|
return (AssertionType) samlParser.parse(samlDocument);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -429,7 +429,7 @@ public class SAML2Response {
|
||||||
SAMLParser samlParser = new SAMLParser();
|
SAMLParser samlParser = new SAMLParser();
|
||||||
JAXPValidationUtil.checkSchemaValidation(samlResponseDocument);
|
JAXPValidationUtil.checkSchemaValidation(samlResponseDocument);
|
||||||
|
|
||||||
ResponseType responseType = (ResponseType) samlParser.parse(DocumentUtil.getNodeAsStream(samlResponseDocument));
|
ResponseType responseType = (ResponseType) samlParser.parse(samlResponseDocument);
|
||||||
|
|
||||||
samlDocumentHolder = new SAMLDocumentHolder(responseType, samlResponseDocument);
|
samlDocumentHolder = new SAMLDocumentHolder(responseType, samlResponseDocument);
|
||||||
return responseType;
|
return responseType;
|
||||||
|
@ -460,8 +460,7 @@ public class SAML2Response {
|
||||||
SAMLParser samlParser = new SAMLParser();
|
SAMLParser samlParser = new SAMLParser();
|
||||||
JAXPValidationUtil.checkSchemaValidation(samlResponseDocument);
|
JAXPValidationUtil.checkSchemaValidation(samlResponseDocument);
|
||||||
|
|
||||||
InputStream responseStream = DocumentUtil.getNodeAsStream(samlResponseDocument);
|
SAML2Object responseType = (SAML2Object) samlParser.parse(samlResponseDocument);
|
||||||
SAML2Object responseType = (SAML2Object) samlParser.parse(responseStream);
|
|
||||||
|
|
||||||
samlDocumentHolder = new SAMLDocumentHolder(responseType, samlResponseDocument);
|
samlDocumentHolder = new SAMLDocumentHolder(responseType, samlResponseDocument);
|
||||||
return responseType;
|
return responseType;
|
||||||
|
|
|
@ -146,7 +146,7 @@ public class SamlEcpProfileTest {
|
||||||
|
|
||||||
assertNotNull(samlResponse);
|
assertNotNull(samlResponse);
|
||||||
|
|
||||||
ResponseType responseType = (ResponseType) new SAMLParser().parse(DocumentUtil.getNodeAsStream(samlResponse));
|
ResponseType responseType = (ResponseType) new SAMLParser().parse(samlResponse);
|
||||||
StatusCodeType statusCode = responseType.getStatus().getStatusCode();
|
StatusCodeType statusCode = responseType.getStatus().getStatusCode();
|
||||||
|
|
||||||
assertEquals(statusCode.getValue().toString(), JBossSAMLURIConstants.STATUS_SUCCESS.get());
|
assertEquals(statusCode.getValue().toString(), JBossSAMLURIConstants.STATUS_SUCCESS.get());
|
||||||
|
@ -229,7 +229,7 @@ public class SamlEcpProfileTest {
|
||||||
|
|
||||||
assertNotNull(samlResponse);
|
assertNotNull(samlResponse);
|
||||||
|
|
||||||
StatusResponseType responseType = (StatusResponseType) new SAMLParser().parse(DocumentUtil.getNodeAsStream(samlResponse));
|
StatusResponseType responseType = (StatusResponseType) new SAMLParser().parse(samlResponse);
|
||||||
StatusCodeType statusCode = responseType.getStatus().getStatusCode();
|
StatusCodeType statusCode = responseType.getStatus().getStatusCode();
|
||||||
|
|
||||||
assertNotEquals(statusCode.getStatusCode().getValue().toString(), JBossSAMLURIConstants.STATUS_SUCCESS.get());
|
assertNotEquals(statusCode.getStatusCode().getValue().toString(), JBossSAMLURIConstants.STATUS_SUCCESS.get());
|
||||||
|
|
Loading…
Reference in a new issue