73e3ed1c02f32e0e74a1b7a10fac04da45cad335.svn-base 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. package org.jeecg.modules.cas.util;
  2. import java.io.StringReader;
  3. import java.util.ArrayList;
  4. import java.util.Collections;
  5. import java.util.HashMap;
  6. import java.util.LinkedList;
  7. import java.util.List;
  8. import java.util.Map;
  9. import javax.xml.XMLConstants;
  10. import javax.xml.parsers.DocumentBuilderFactory;
  11. import javax.xml.parsers.ParserConfigurationException;
  12. import javax.xml.parsers.SAXParser;
  13. import javax.xml.parsers.SAXParserFactory;
  14. import org.w3c.dom.Document;
  15. import org.xml.sax.Attributes;
  16. import org.xml.sax.InputSource;
  17. import org.xml.sax.SAXException;
  18. import org.xml.sax.XMLReader;
  19. import org.xml.sax.helpers.DefaultHandler;
  20. import lombok.extern.slf4j.Slf4j;
  21. /**
  22. * 解析cas,ST验证后的xml
  23. *
  24. */
  25. @Slf4j
  26. public final class XmlUtils {
  27. /**
  28. * Creates a new namespace-aware DOM document object by parsing the given XML.
  29. *
  30. * @param xml XML content.
  31. *
  32. * @return DOM document.
  33. */
  34. public static Document newDocument(final String xml) {
  35. final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  36. final Map<String, Boolean> features = new HashMap<String, Boolean>();
  37. features.put(XMLConstants.FEATURE_SECURE_PROCESSING, true);
  38. features.put("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
  39. for (final Map.Entry<String, Boolean> entry : features.entrySet()) {
  40. try {
  41. factory.setFeature(entry.getKey(), entry.getValue());
  42. } catch (ParserConfigurationException e) {
  43. log.warn("Failed setting XML feature {}: {}", entry.getKey(), e);
  44. }
  45. }
  46. factory.setNamespaceAware(true);
  47. try {
  48. return factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
  49. } catch (Exception e) {
  50. throw new RuntimeException("XML parsing error: " + e);
  51. }
  52. }
  53. /**
  54. * Get an instance of an XML reader from the XMLReaderFactory.
  55. *
  56. * @return the XMLReader.
  57. */
  58. public static XMLReader getXmlReader() {
  59. try {
  60. final XMLReader reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
  61. reader.setFeature("http://xml.org/sax/features/namespaces", true);
  62. reader.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
  63. reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
  64. return reader;
  65. } catch (final Exception e) {
  66. throw new RuntimeException("Unable to create XMLReader", e);
  67. }
  68. }
  69. /**
  70. * Retrieve the text for a group of elements. Each text element is an entry
  71. * in a list.
  72. * <p>This method is currently optimized for the use case of two elements in a list.
  73. *
  74. * @param xmlAsString the xml response
  75. * @param element the element to look for
  76. * @return the list of text from the elements.
  77. */
  78. public static List<String> getTextForElements(final String xmlAsString, final String element) {
  79. final List<String> elements = new ArrayList<String>(2);
  80. final XMLReader reader = getXmlReader();
  81. final DefaultHandler handler = new DefaultHandler() {
  82. private boolean foundElement = false;
  83. private StringBuilder buffer = new StringBuilder();
  84. public void startElement(final String uri, final String localName, final String qName,
  85. final Attributes attributes) throws SAXException {
  86. if (localName.equals(element)) {
  87. this.foundElement = true;
  88. }
  89. }
  90. public void endElement(final String uri, final String localName, final String qName) throws SAXException {
  91. if (localName.equals(element)) {
  92. this.foundElement = false;
  93. elements.add(this.buffer.toString());
  94. this.buffer = new StringBuilder();
  95. }
  96. }
  97. public void characters(char[] ch, int start, int length) throws SAXException {
  98. if (this.foundElement) {
  99. this.buffer.append(ch, start, length);
  100. }
  101. }
  102. };
  103. reader.setContentHandler(handler);
  104. reader.setErrorHandler(handler);
  105. try {
  106. reader.parse(new InputSource(new StringReader(xmlAsString)));
  107. } catch (final Exception e) {
  108. log.error(e.getMessage(), e);
  109. return null;
  110. }
  111. return elements;
  112. }
  113. /**
  114. * Retrieve the text for a specific element (when we know there is only
  115. * one).
  116. *
  117. * @param xmlAsString the xml response
  118. * @param element the element to look for
  119. * @return the text value of the element.
  120. */
  121. public static String getTextForElement(final String xmlAsString, final String element) {
  122. final XMLReader reader = getXmlReader();
  123. final StringBuilder builder = new StringBuilder();
  124. final DefaultHandler handler = new DefaultHandler() {
  125. private boolean foundElement = false;
  126. public void startElement(final String uri, final String localName, final String qName,
  127. final Attributes attributes) throws SAXException {
  128. if (localName.equals(element)) {
  129. this.foundElement = true;
  130. }
  131. }
  132. public void endElement(final String uri, final String localName, final String qName) throws SAXException {
  133. if (localName.equals(element)) {
  134. this.foundElement = false;
  135. }
  136. }
  137. public void characters(char[] ch, int start, int length) throws SAXException {
  138. if (this.foundElement) {
  139. builder.append(ch, start, length);
  140. }
  141. }
  142. };
  143. reader.setContentHandler(handler);
  144. reader.setErrorHandler(handler);
  145. try {
  146. reader.parse(new InputSource(new StringReader(xmlAsString)));
  147. } catch (final Exception e) {
  148. log.error(e.getMessage(), e);
  149. return null;
  150. }
  151. return builder.toString();
  152. }
  153. public static Map<String, Object> extractCustomAttributes(final String xml) {
  154. final SAXParserFactory spf = SAXParserFactory.newInstance();
  155. spf.setNamespaceAware(true);
  156. spf.setValidating(false);
  157. try {
  158. final SAXParser saxParser = spf.newSAXParser();
  159. final XMLReader xmlReader = saxParser.getXMLReader();
  160. final CustomAttributeHandler handler = new CustomAttributeHandler();
  161. xmlReader.setContentHandler(handler);
  162. xmlReader.parse(new InputSource(new StringReader(xml)));
  163. return handler.getAttributes();
  164. } catch (final Exception e) {
  165. log.error(e.getMessage(), e);
  166. return Collections.emptyMap();
  167. }
  168. }
  169. private static class CustomAttributeHandler extends DefaultHandler {
  170. private Map<String, Object> attributes;
  171. private boolean foundAttributes;
  172. private String currentAttribute;
  173. private StringBuilder value;
  174. @Override
  175. public void startDocument() throws SAXException {
  176. this.attributes = new HashMap<String, Object>();
  177. }
  178. @Override
  179. public void startElement(final String namespaceURI, final String localName, final String qName,
  180. final Attributes attributes) throws SAXException {
  181. if ("attributes".equals(localName)) {
  182. this.foundAttributes = true;
  183. } else if (this.foundAttributes) {
  184. this.value = new StringBuilder();
  185. this.currentAttribute = localName;
  186. }
  187. }
  188. @Override
  189. public void characters(final char[] chars, final int start, final int length) throws SAXException {
  190. if (this.currentAttribute != null) {
  191. value.append(chars, start, length);
  192. }
  193. }
  194. @Override
  195. public void endElement(final String namespaceURI, final String localName, final String qName)
  196. throws SAXException {
  197. if ("attributes".equals(localName)) {
  198. this.foundAttributes = false;
  199. this.currentAttribute = null;
  200. } else if (this.foundAttributes) {
  201. final Object o = this.attributes.get(this.currentAttribute);
  202. if (o == null) {
  203. this.attributes.put(this.currentAttribute, this.value.toString());
  204. } else {
  205. final List<Object> items;
  206. if (o instanceof List) {
  207. items = (List<Object>) o;
  208. } else {
  209. items = new LinkedList<Object>();
  210. items.add(o);
  211. this.attributes.put(this.currentAttribute, items);
  212. }
  213. items.add(this.value.toString());
  214. }
  215. }
  216. }
  217. public Map<String, Object> getAttributes() {
  218. return this.attributes;
  219. }
  220. }
  221. public static void main(String[] args) {
  222. String result = "<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>\r\n" +
  223. " <cas:authenticationSuccess>\r\n" +
  224. " <cas:user>admin</cas:user>\r\n" +
  225. " <cas:attributes>\r\n" +
  226. " <cas:credentialType>UsernamePasswordCredential</cas:credentialType>\r\n" +
  227. " <cas:isFromNewLogin>true</cas:isFromNewLogin>\r\n" +
  228. " <cas:authenticationDate>2019-08-01T19:33:21.527+08:00[Asia/Shanghai]</cas:authenticationDate>\r\n" +
  229. " <cas:authenticationMethod>RestAuthenticationHandler</cas:authenticationMethod>\r\n" +
  230. " <cas:successfulAuthenticationHandlers>RestAuthenticationHandler</cas:successfulAuthenticationHandlers>\r\n" +
  231. " <cas:longTermAuthenticationRequestTokenUsed>false</cas:longTermAuthenticationRequestTokenUsed>\r\n" +
  232. " </cas:attributes>\r\n" +
  233. " </cas:authenticationSuccess>\r\n" +
  234. "</cas:serviceResponse>";
  235. String errorRes = "<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>\r\n" +
  236. " <cas:authenticationFailure code=\"INVALID_TICKET\">未能够识别出目标 &#39;ST-5-1g-9cNES6KXNRwq-GuRET103sm0-DESKTOP-VKLS8B3&#39;票根</cas:authenticationFailure>\r\n" +
  237. "</cas:serviceResponse>";
  238. String error = XmlUtils.getTextForElement(errorRes, "authenticationFailure");
  239. System.out.println("------"+error);
  240. String error2 = XmlUtils.getTextForElement(result, "authenticationFailure");
  241. System.out.println("------"+error2);
  242. String principal = XmlUtils.getTextForElement(result, "user");
  243. System.out.println("---principal---"+principal);
  244. Map<String, Object> attributes = XmlUtils.extractCustomAttributes(result);
  245. System.out.println("---attributes---"+attributes);
  246. }
  247. }