123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- package org.jeecg.modules.cas.util;
- import java.io.StringReader;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.Map;
- import javax.xml.XMLConstants;
- import javax.xml.parsers.DocumentBuilderFactory;
- import javax.xml.parsers.ParserConfigurationException;
- import javax.xml.parsers.SAXParser;
- import javax.xml.parsers.SAXParserFactory;
- import org.w3c.dom.Document;
- import org.xml.sax.Attributes;
- import org.xml.sax.InputSource;
- import org.xml.sax.SAXException;
- import org.xml.sax.XMLReader;
- import org.xml.sax.helpers.DefaultHandler;
- import lombok.extern.slf4j.Slf4j;
- /**
- * 解析cas,ST验证后的xml
- *
- */
- @Slf4j
- public final class XmlUtils {
- /**
- * Creates a new namespace-aware DOM document object by parsing the given XML.
- *
- * @param xml XML content.
- *
- * @return DOM document.
- */
- public static Document newDocument(final String xml) {
- final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- final Map<String, Boolean> features = new HashMap<String, Boolean>();
- features.put(XMLConstants.FEATURE_SECURE_PROCESSING, true);
- features.put("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
- for (final Map.Entry<String, Boolean> entry : features.entrySet()) {
- try {
- factory.setFeature(entry.getKey(), entry.getValue());
- } catch (ParserConfigurationException e) {
- log.warn("Failed setting XML feature {}: {}", entry.getKey(), e);
- }
- }
- factory.setNamespaceAware(true);
- try {
- return factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
- } catch (Exception e) {
- throw new RuntimeException("XML parsing error: " + e);
- }
- }
- /**
- * Get an instance of an XML reader from the XMLReaderFactory.
- *
- * @return the XMLReader.
- */
- public static XMLReader getXmlReader() {
- try {
- final XMLReader reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
- reader.setFeature("http://xml.org/sax/features/namespaces", true);
- reader.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
- reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
- return reader;
- } catch (final Exception e) {
- throw new RuntimeException("Unable to create XMLReader", e);
- }
- }
- /**
- * Retrieve the text for a group of elements. Each text element is an entry
- * in a list.
- * <p>This method is currently optimized for the use case of two elements in a list.
- *
- * @param xmlAsString the xml response
- * @param element the element to look for
- * @return the list of text from the elements.
- */
- public static List<String> getTextForElements(final String xmlAsString, final String element) {
- final List<String> elements = new ArrayList<String>(2);
- final XMLReader reader = getXmlReader();
- final DefaultHandler handler = new DefaultHandler() {
- private boolean foundElement = false;
- private StringBuilder buffer = new StringBuilder();
- public void startElement(final String uri, final String localName, final String qName,
- final Attributes attributes) throws SAXException {
- if (localName.equals(element)) {
- this.foundElement = true;
- }
- }
- public void endElement(final String uri, final String localName, final String qName) throws SAXException {
- if (localName.equals(element)) {
- this.foundElement = false;
- elements.add(this.buffer.toString());
- this.buffer = new StringBuilder();
- }
- }
- public void characters(char[] ch, int start, int length) throws SAXException {
- if (this.foundElement) {
- this.buffer.append(ch, start, length);
- }
- }
- };
- reader.setContentHandler(handler);
- reader.setErrorHandler(handler);
- try {
- reader.parse(new InputSource(new StringReader(xmlAsString)));
- } catch (final Exception e) {
- log.error(e.getMessage(), e);
- return null;
- }
- return elements;
- }
- /**
- * Retrieve the text for a specific element (when we know there is only
- * one).
- *
- * @param xmlAsString the xml response
- * @param element the element to look for
- * @return the text value of the element.
- */
- public static String getTextForElement(final String xmlAsString, final String element) {
- final XMLReader reader = getXmlReader();
- final StringBuilder builder = new StringBuilder();
- final DefaultHandler handler = new DefaultHandler() {
- private boolean foundElement = false;
- public void startElement(final String uri, final String localName, final String qName,
- final Attributes attributes) throws SAXException {
- if (localName.equals(element)) {
- this.foundElement = true;
- }
- }
- public void endElement(final String uri, final String localName, final String qName) throws SAXException {
- if (localName.equals(element)) {
- this.foundElement = false;
- }
- }
- public void characters(char[] ch, int start, int length) throws SAXException {
- if (this.foundElement) {
- builder.append(ch, start, length);
- }
- }
- };
- reader.setContentHandler(handler);
- reader.setErrorHandler(handler);
- try {
- reader.parse(new InputSource(new StringReader(xmlAsString)));
- } catch (final Exception e) {
- log.error(e.getMessage(), e);
- return null;
- }
- return builder.toString();
- }
-
-
- public static Map<String, Object> extractCustomAttributes(final String xml) {
- final SAXParserFactory spf = SAXParserFactory.newInstance();
- spf.setNamespaceAware(true);
- spf.setValidating(false);
- try {
- final SAXParser saxParser = spf.newSAXParser();
- final XMLReader xmlReader = saxParser.getXMLReader();
- final CustomAttributeHandler handler = new CustomAttributeHandler();
- xmlReader.setContentHandler(handler);
- xmlReader.parse(new InputSource(new StringReader(xml)));
- return handler.getAttributes();
- } catch (final Exception e) {
- log.error(e.getMessage(), e);
- return Collections.emptyMap();
- }
- }
-
- private static class CustomAttributeHandler extends DefaultHandler {
- private Map<String, Object> attributes;
- private boolean foundAttributes;
- private String currentAttribute;
- private StringBuilder value;
- @Override
- public void startDocument() throws SAXException {
- this.attributes = new HashMap<String, Object>();
- }
- @Override
- public void startElement(final String namespaceURI, final String localName, final String qName,
- final Attributes attributes) throws SAXException {
- if ("attributes".equals(localName)) {
- this.foundAttributes = true;
- } else if (this.foundAttributes) {
- this.value = new StringBuilder();
- this.currentAttribute = localName;
- }
- }
- @Override
- public void characters(final char[] chars, final int start, final int length) throws SAXException {
- if (this.currentAttribute != null) {
- value.append(chars, start, length);
- }
- }
- @Override
- public void endElement(final String namespaceURI, final String localName, final String qName)
- throws SAXException {
- if ("attributes".equals(localName)) {
- this.foundAttributes = false;
- this.currentAttribute = null;
- } else if (this.foundAttributes) {
- final Object o = this.attributes.get(this.currentAttribute);
- if (o == null) {
- this.attributes.put(this.currentAttribute, this.value.toString());
- } else {
- final List<Object> items;
- if (o instanceof List) {
- items = (List<Object>) o;
- } else {
- items = new LinkedList<Object>();
- items.add(o);
- this.attributes.put(this.currentAttribute, items);
- }
- items.add(this.value.toString());
- }
- }
- }
- public Map<String, Object> getAttributes() {
- return this.attributes;
- }
- }
-
-
- public static void main(String[] args) {
- String result = "<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>\r\n" +
- " <cas:authenticationSuccess>\r\n" +
- " <cas:user>admin</cas:user>\r\n" +
- " <cas:attributes>\r\n" +
- " <cas:credentialType>UsernamePasswordCredential</cas:credentialType>\r\n" +
- " <cas:isFromNewLogin>true</cas:isFromNewLogin>\r\n" +
- " <cas:authenticationDate>2019-08-01T19:33:21.527+08:00[Asia/Shanghai]</cas:authenticationDate>\r\n" +
- " <cas:authenticationMethod>RestAuthenticationHandler</cas:authenticationMethod>\r\n" +
- " <cas:successfulAuthenticationHandlers>RestAuthenticationHandler</cas:successfulAuthenticationHandlers>\r\n" +
- " <cas:longTermAuthenticationRequestTokenUsed>false</cas:longTermAuthenticationRequestTokenUsed>\r\n" +
- " </cas:attributes>\r\n" +
- " </cas:authenticationSuccess>\r\n" +
- "</cas:serviceResponse>";
-
- String errorRes = "<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>\r\n" +
- " <cas:authenticationFailure code=\"INVALID_TICKET\">未能够识别出目标 'ST-5-1g-9cNES6KXNRwq-GuRET103sm0-DESKTOP-VKLS8B3'票根</cas:authenticationFailure>\r\n" +
- "</cas:serviceResponse>";
-
- String error = XmlUtils.getTextForElement(errorRes, "authenticationFailure");
- System.out.println("------"+error);
-
- String error2 = XmlUtils.getTextForElement(result, "authenticationFailure");
- System.out.println("------"+error2);
- String principal = XmlUtils.getTextForElement(result, "user");
- System.out.println("---principal---"+principal);
- Map<String, Object> attributes = XmlUtils.extractCustomAttributes(result);
- System.out.println("---attributes---"+attributes);
- }
- }
|