Untitled
import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.HashMap; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import java.io.StringWriter; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; public class SAMLDecoder { public static class SAMLResponse { private String issuer; private String nameId; private String recipient; private Map<String, String> attributes; public SAMLResponse() { this.attributes = new HashMap<>(); } // Getters and setters public String getIssuer() { return issuer; } public void setIssuer(String issuer) { this.issuer = issuer; } public String getNameId() { return nameId; } public void setNameId(String nameId) { this.nameId = nameId; } public String getRecipient() { return recipient; } public void setRecipient(String recipient) { this.recipient = recipient; } public Map<String, String> getAttributes() { return attributes; } } public static SAMLResponse decodeSAMLResponseFromFile(File file) throws Exception { SAMLResponse response = new SAMLResponse(); // Create a buffered reader with a large buffer size try (BufferedReader reader = new BufferedReader( new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8), 8192 * 4)) { // 32KB buffer // Read and decode the base64 content in chunks StringBuilder base64Content = new StringBuilder(); char[] buffer = new char[8192]; // 8KB chunks int bytesRead; while ((bytesRead = reader.read(buffer)) != -1) { base64Content.append(buffer, 0, bytesRead); } // Create decoder that can handle large content Base64.Decoder decoder = Base64.getMimeDecoder(); byte[] decodedBytes = decoder.decode(base64Content.toString().replaceAll("\\s+", "")); // Create XML input factory for streaming XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); // Disable external entity processing xmlInputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false); // Create XML stream reader XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader( new ByteArrayInputStream(decodedBytes)); // Process XML stream String currentElement = ""; while (xmlStreamReader.hasNext()) { int event = xmlStreamReader.next(); switch (event) { case XMLStreamReader.START_ELEMENT: currentElement = xmlStreamReader.getLocalName(); if ("Issuer".equals(currentElement)) { response.setIssuer(xmlStreamReader.getElementText()); } else if ("NameID".equals(currentElement)) { response.setNameId(xmlStreamReader.getElementText()); } else if ("SubjectConfirmationData".equals(currentElement)) { response.setRecipient(xmlStreamReader.getAttributeValue(null, "Recipient")); } else if ("Attribute".equals(currentElement)) { String attributeName = xmlStreamReader.getAttributeValue(null, "Name"); // Get the attribute value in the next iteration while (xmlStreamReader.hasNext()) { event = xmlStreamReader.next(); if (event == XMLStreamReader.START_ELEMENT && "AttributeValue".equals(xmlStreamReader.getLocalName())) { String attributeValue = xmlStreamReader.getElementText(); response.getAttributes().put(attributeName, attributeValue); break; } } } break; } } xmlStreamReader.close(); } return response; } public static void streamProcessLargeSAMLResponse(File inputFile, File outputFile) throws Exception { try (BufferedReader reader = new BufferedReader( new InputStreamReader(new FileInputStream(inputFile), StandardCharsets.UTF_8), 8192 * 4)) { // Process in chunks and write to output file Base64.Decoder decoder = Base64.getMimeDecoder(); java.io.FileOutputStream fos = new java.io.FileOutputStream(outputFile); char[] buffer = new char[8192]; int bytesRead; byte[] decodedChunk; while ((bytesRead = reader.read(buffer)) != -1) { if (bytesRead > 0) { String chunk = new String(buffer, 0, bytesRead); // Remove whitespace and decode decodedChunk = decoder.decode(chunk.replaceAll("\\s+", "")); fos.write(decodedChunk); } } fos.close(); } } // Example usage public static void main(String[] args) { try { // For huge SAML response stored in a file File inputFile = new File("huge_saml_response.txt"); // Option 1: Parse and get structured data SAMLResponse response = decodeSAMLResponseFromFile(inputFile); System.out.println("Issuer: " + response.getIssuer()); System.out.println("NameID: " + response.getNameId()); System.out.println("Recipient: " + response.getRecipient()); System.out.println("\nAttributes:"); response.getAttributes().forEach((key, value) -> System.out.println(key + ": " + value)); // Option 2: Just decode to a new file File outputFile = new File("decoded_saml.xml"); streamProcessLargeSAMLResponse(inputFile, outputFile); } catch (Exception e) { e.printStackTrace(); } } }
Leave a Comment