From 980d0ff116b7aa7d49fece1904f34f0b11076346 Mon Sep 17 00:00:00 2001 From: Scott Battaglia Date: Sun, 6 Jan 2013 23:40:46 -0500 Subject: [PATCH 1/3] CASC-196 real XML parsing example if using . Updated tests to make sure it works if there are line breaks. --- .../Cas20ServiceTicketValidator.java | 87 ++++++++++++++----- .../Cas20ServiceTicketValidatorTests.java | 3 +- 2 files changed, 69 insertions(+), 21 deletions(-) diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java index 627ca9a..f4ffa50 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java @@ -27,7 +27,16 @@ import org.jasig.cas.client.proxy.ProxyRetriever; import org.jasig.cas.client.util.CommonUtils; import org.jasig.cas.client.util.XmlUtils; import org.w3c.dom.NodeList; +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 javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import java.io.StringReader; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -128,27 +137,18 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick * @return the map of attributes. */ protected Map extractCustomAttributes(final String xml) { - - if (!xml.contains("")) { - return new HashMap(); - } - - final Map attributes = new HashMap(); - + final SAXParserFactory spf = SAXParserFactory.newInstance(); + spf.setNamespaceAware(true); + spf.setValidating(false); try { - NodeList nodeList = XmlUtils.getNodeListForElements(xml,"cas:attributes"); - for (int i = 0; i < nodeList.getLength(); i++) { - final String nodeName = nodeList.item(i).getNodeName(); - final int beginIndex = nodeName.indexOf(":") + 1; - final int endIndex = nodeList.item(i).getNodeName().length(); - - final String attributeName = nodeName.substring(beginIndex, endIndex); // remove the "cas:" prefix from node name - final Object attributeValue = nodeList.item(i).getTextContent(); - attributes.put(attributeName, attributeValue); - } - return attributes; - - } catch (Exception e) { + 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(); } } @@ -187,4 +187,51 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick protected final ProxyRetriever getProxyRetriever() { return this.proxyRetriever; } + + private class CustomAttributeHandler extends DefaultHandler { + + private Map attributes; + + private boolean foundAttributes; + + private String currentAttribute; + + private StringBuilder value; + + @Override + public void startDocument() throws SAXException { + this.attributes = new HashMap(); + } + + @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) { + this.attributes.put(currentAttribute, value.toString()); + } + } + + public Map getAttributes() { + return this.attributes; + } + } } diff --git a/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidatorTests.java b/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidatorTests.java index c250969..0b1f137 100644 --- a/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidatorTests.java +++ b/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidatorTests.java @@ -139,13 +139,14 @@ public final class Cas20ServiceTicketValidatorTests extends AbstractTicketValida + USERNAME + "" + PGTIOU - + "testid"; + + "testidtest1\n\ntest"; server.content = RESPONSE.getBytes(server.encoding); final Assertion assertion = this.ticketValidator.validate("test", "test"); assertEquals(USERNAME, assertion.getPrincipal().getName()); assertEquals("test", assertion.getPrincipal().getAttributes().get("password")); assertEquals("id", assertion.getPrincipal().getAttributes().get("eduPersonId")); + assertEquals("test1\n\ntest", assertion.getPrincipal().getAttributes().get("longAttribute")); //assertEquals(PGT, assertion.getProxyGrantingTicketId()); } From 5af7c331b75b7b38f2ab3f384c005ab49819c741 Mon Sep 17 00:00:00 2001 From: Scott Battaglia Date: Mon, 7 Jan 2013 22:51:45 -0500 Subject: [PATCH 2/3] CASC-179 added parameter to determine whether to create sessions. Also, now properly does a return. --- .../cas/client/session/SingleSignOutFilter.java | 1 + .../cas/client/session/SingleSignOutHandler.java | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutFilter.java index a9b4390..a9c8504 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutFilter.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutFilter.java @@ -45,6 +45,7 @@ public final class SingleSignOutFilter extends AbstractConfigurationFilter { handler.setArtifactParameterName(getPropertyFromInitParams(filterConfig, "artifactParameterName", "ticket")); handler.setLogoutParameterName(getPropertyFromInitParams(filterConfig, "logoutParameterName", "logoutRequest")); handler.setArtifactParameterOverPost(parseBoolean(getPropertyFromInitParams(filterConfig, "artifactParameterOverPost", "false"))); + handler.setEagerlyCreateSessions(parseBoolean(getPropertyFromInitParams(filterConfig, "eagerlyCreateSessions", "true"))); } handler.init(); } diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutHandler.java b/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutHandler.java index 31f3e24..a1c1fa5 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutHandler.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutHandler.java @@ -54,6 +54,8 @@ public final class SingleSignOutHandler { private boolean artifactParameterOverPost = false; + private boolean eagerlyCreateSessions = true; + private List safeParameters; @@ -83,6 +85,10 @@ public final class SingleSignOutHandler { this.logoutParameterName = name; } + public void setEagerlyCreateSessions(final boolean eagerlyCreateSessions) { + this.eagerlyCreateSessions = eagerlyCreateSessions; + } + /** * Initializes the component for use. */ @@ -128,7 +134,12 @@ public final class SingleSignOutHandler { * @param request HTTP request containing an authentication token. */ public void recordSession(final HttpServletRequest request) { - final HttpSession session = request.getSession(true); + final HttpSession session = request.getSession(this.eagerlyCreateSessions); + + if (session == null) { + log.debug("No session currently exists (and none created). Cannot record session information for single sign out."); + return; + } final String token = CommonUtils.safeGetParameter(request, this.artifactParameterName, this.safeParameters); if (log.isDebugEnabled()) { From 67bb0a6ef83801a26d3e3898884aa10a429f6245 Mon Sep 17 00:00:00 2001 From: Scott Battaglia Date: Mon, 7 Jan 2013 23:10:24 -0500 Subject: [PATCH 3/3] CASC-196 re-add support for multi-valued attributes --- .../Cas20ServiceTicketValidator.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java index f4ffa50..99637ac 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java @@ -36,10 +36,7 @@ import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import java.io.StringReader; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.util.*; /** * Implementation of the TicketValidator that will validate Service Tickets in compliance with the CAS 2. @@ -226,7 +223,21 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick this.foundAttributes = false; this.currentAttribute = null; } else if (this.foundAttributes) { - this.attributes.put(currentAttribute, value.toString()); + final Object o = this.attributes.get(this.currentAttribute); + + if (o == null) { + this.attributes.put(this.currentAttribute, this.value.toString()); + } else { + final List items; + if (o instanceof List) { + items = (List) o; + } else { + items = new LinkedList(); + items.add(o); + this.attributes.put(this.currentAttribute, items); + } + items.add(this.value.toString()); + } } }