list = builder.getQueryParams();
+ for (URIBuilder.BasicNameValuePair pair : list) {
+ assertEquals(pair.getName(), "foo");
+ assertTrue(pair.getValue().equals("three") || pair.getValue().equals("bar"));
+ }
+ assertEquals(list.size(), 2);
+ assertEquals("blah", builder.getFragment());
+ }
+
+ @Test
+ public void constructFromUriAndBack() {
+ URI uri = URI.create("http://apache.org/foo/bar?foo=bar&a=b&c=d&y=z&foo=zoo#foo");
+ URIBuilder builder = new URIBuilder(uri);
+
+ assertEquals(uri, builder.build());
+ }
+
+ @Test
+ public void constructFromUriAndModify() {
+ URI uri = URI.create("http://apache.org/foo/bar?foo=bar#foo");
+ URIBuilder builder = new URIBuilder(uri);
+
+ builder.setHost("example.org");
+ builder.addParameter("bar", "foo");
+
+ assertEquals("http://example.org/foo/bar?foo=bar&bar=foo#foo", builder.toString());
+ }
+
+ @Test
+ public void equalsAndHashCodeOk() {
+ URIBuilder uri = new URIBuilder().digestURI(URI.create("http://example.org/foo/bar/baz?blah=blah#boo"));
+ URIBuilder uri2 = new URIBuilder(URI.create("http://example.org/foo/bar/baz?blah=blah#boo"));
+
+ assertEquals(uri, uri2);
+ assertEquals(uri2, uri);
+
+ assertEquals(uri, uri);
+
+ assertNotNull(uri);
+ assertNotSame(uri, "http://example.org/foo/bar/baz?blah=blah#boo");
+ assertNotSame(uri, URI.create("http://example.org/foo/bar/baz?blah=blah#boo"));
+ assertEquals(uri.hashCode(), uri2.hashCode());
+ }
+
+
+}
diff --git a/cas-client-core/src/test/java/org/jasig/cas/client/validation/AssertionImplTests.java b/cas-client-core/src/test/java/org/jasig/cas/client/validation/AssertionImplTests.java
index de6e856..335dbe6 100644
--- a/cas-client-core/src/test/java/org/jasig/cas/client/validation/AssertionImplTests.java
+++ b/cas-client-core/src/test/java/org/jasig/cas/client/validation/AssertionImplTests.java
@@ -18,6 +18,7 @@
*/
package org.jasig.cas.client.validation;
+import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import junit.framework.TestCase;
@@ -49,6 +50,11 @@ public final class AssertionImplTests extends TestCase {
assertNull(assertion.getPrincipal().getProxyTicketFor("test"));
}
+ public void testAssertionValidity() throws Exception {
+ final Assertion assertion = new AssertionImpl(CONST_PRINCIPAL, new Date(), new Date(), new Date(), CONST_ATTRIBUTES);
+ assertTrue(assertion.isValid());
+ }
+
public void testCompleteConstructor() {
final Assertion assertion = new AssertionImpl(CONST_PRINCIPAL, CONST_ATTRIBUTES);
diff --git a/cas-client-integration-atlassian/pom.xml b/cas-client-integration-atlassian/pom.xml
index df787e6..9c1c7b0 100644
--- a/cas-client-integration-atlassian/pom.xml
+++ b/cas-client-integration-atlassian/pom.xml
@@ -5,7 +5,6 @@
cas-client
4.0.0
- org.jasig.cas.client
cas-client-integration-atlassian
jar
Jasig CAS Client for Java - Atlassian Integration
diff --git a/cas-client-integration-jboss/pom.xml b/cas-client-integration-jboss/pom.xml
index 1e97cd9..2cf256d 100644
--- a/cas-client-integration-jboss/pom.xml
+++ b/cas-client-integration-jboss/pom.xml
@@ -5,7 +5,6 @@
cas-client
4.0.0
- org.jasig.cas.client
cas-client-integration-jboss
jar
Jasig CAS Client for Java - JBoss Integration
diff --git a/cas-client-integration-jetty/pom.xml b/cas-client-integration-jetty/pom.xml
new file mode 100644
index 0000000..2faefd2
--- /dev/null
+++ b/cas-client-integration-jetty/pom.xml
@@ -0,0 +1,72 @@
+
+
+
+ cas-client
+ org.jasig.cas.client
+ 3.5.0-SNAPSHOT
+
+ 4.0.0
+
+ cas-client-integration-jetty
+ jar
+ Jasig CAS Client for Java - Jetty Container Integration
+
+
+
+ 9.2.14.v20151106
+
+
+
+
+ org.jasig.cas.client
+ cas-client-core
+ ${project.version}
+
+
+ org.eclipse.jetty
+ jetty-security
+ ${jetty.version}
+
+
+
+
+ org.jasig.cas.client
+ cas-client-core
+ ${project.version}
+ test-jar
+ test
+
+
+ org.eclipse.jetty
+ jetty-webapp
+ ${jetty.version}
+ test
+
+
+ org.eclipse.jetty
+ jetty-plus
+ ${jetty.version}
+ test
+
+
+ org.eclipse.jetty
+ jetty-annotations
+ ${jetty.version}
+ test
+
+
+ org.eclipse.jetty
+ apache-jsp
+ ${jetty.version}
+ test
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.1.0
+ provided
+
+
+
+
+
diff --git a/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasAuthentication.java b/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasAuthentication.java
new file mode 100644
index 0000000..831ec75
--- /dev/null
+++ b/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasAuthentication.java
@@ -0,0 +1,46 @@
+package org.jasig.cas.client.jetty;
+
+import org.eclipse.jetty.security.UserAuthentication;
+import org.jasig.cas.client.util.CommonUtils;
+import org.jasig.cas.client.validation.Assertion;
+
+/**
+ * CAS-specific user authentication.
+ *
+ * @author Marvin S. Addison
+ */
+public class CasAuthentication extends UserAuthentication {
+
+ /** CAS authenticator that produced this authentication. */
+ private final CasAuthenticator authenticator;
+
+ /** CAS ticket that was successfully validated to permit authentication. */
+ private final String ticket;
+
+
+ /**
+ * Creates a new instance.
+ *
+ * @param authenticator The authenticator that produced this authentication.
+ * @param ticket The CAS ticket that was successfully validated to permit authentication.
+ * @param assertion The CAS assertion produced from successful ticket validation.
+ */
+ public CasAuthentication(final CasAuthenticator authenticator, final String ticket, final Assertion assertion) {
+ super(authenticator.getAuthMethod(), new CasUserIdentity(assertion, authenticator.getRoleAttribute()));
+ CommonUtils.assertNotNull(ticket, "Ticket cannot be null");
+ CommonUtils.assertNotNull(authenticator, "CasAuthenticator cannot be null");
+ this.authenticator = authenticator;
+ this.ticket = ticket;
+ }
+
+ /** @return The CAS ticket that was successfully validated to permit authentication. */
+ public String getTicket() {
+ return ticket;
+ }
+
+ @Override
+ public void logout() {
+ super.logout();
+ this.authenticator.clearCachedAuthentication(ticket);
+ }
+}
diff --git a/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasAuthenticator.java b/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasAuthenticator.java
new file mode 100644
index 0000000..21d4c51
--- /dev/null
+++ b/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasAuthenticator.java
@@ -0,0 +1,248 @@
+/*
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work
+ * for additional information regarding copyright ownership.
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a
+ * copy of the License at the following location:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jasig.cas.client.jetty;
+
+import org.eclipse.jetty.security.Authenticator;
+import org.eclipse.jetty.security.ServerAuthException;
+import org.eclipse.jetty.server.Authentication;
+import org.eclipse.jetty.util.component.AbstractLifeCycle;
+import org.jasig.cas.client.Protocol;
+import org.jasig.cas.client.util.CommonUtils;
+import org.jasig.cas.client.util.ReflectUtils;
+import org.jasig.cas.client.validation.AbstractCasProtocolUrlBasedTicketValidator;
+import org.jasig.cas.client.validation.AbstractUrlBasedTicketValidator;
+import org.jasig.cas.client.validation.Assertion;
+import org.jasig.cas.client.validation.TicketValidator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Jetty authenticator component for container-managed CAS authentication.
+ * NOTE: This component does not support CAS gateway mode.
+ *
+ * @author Marvin S. Addison
+ * @since 3.4.2
+ */
+public class CasAuthenticator extends AbstractLifeCycle implements Authenticator {
+
+ /** Name of authentication method provided by this authenticator. */
+ public static final String AUTH_METHOD = "CAS";
+
+ /** Session attribute used to cache CAS authentication data. */
+ private static final String CACHED_AUTHN_ATTRIBUTE = "org.jasig.cas.client.jetty.Authentication";
+
+ /** Logger instance. */
+ private final Logger logger = LoggerFactory.getLogger(CasAuthenticator.class);
+
+ /** Map of tickets to sessions. */
+ private final ConcurrentMap> sessionMap =
+ new ConcurrentHashMap>();
+
+ /** CAS ticket validator component. */
+ private TicketValidator ticketValidator;
+
+ /** Space-delimited list of server names. */
+ private String serverNames;
+
+ /** CAS principal attribute containing role data. */
+ private String roleAttribute;
+
+ /** URL to /login URI on CAS server. */
+ private String casServerLoginUrl;
+
+ /** Protocol used by ticket validator. */
+ private Protocol protocol;
+
+ /** CAS renew parameter. */
+ private boolean renew;
+
+
+ /**
+ * Sets the CAS ticket validator component.
+ *
+ * @param ticketValidator Ticket validator, MUST NOT be null.
+ */
+ public void setTicketValidator(final TicketValidator ticketValidator) {
+ CommonUtils.assertNotNull(ticketValidator, "TicketValidator cannot be null");
+ if (ticketValidator instanceof AbstractUrlBasedTicketValidator) {
+ if (ticketValidator instanceof AbstractCasProtocolUrlBasedTicketValidator) {
+ protocol = Protocol.CAS2;
+ } else {
+ protocol = Protocol.SAML11;
+ }
+ casServerLoginUrl = ReflectUtils.getField("casServerUrlPrefix", ticketValidator) + "/login";
+ renew = (Boolean) ReflectUtils.getField("renew", ticketValidator);
+ } else {
+ throw new IllegalArgumentException("Unsupported ticket validator " + ticketValidator);
+ }
+ this.ticketValidator = ticketValidator;
+ }
+
+ /**
+ * Sets the names of the server host running Jetty.
+ *
+ * @param nameList Space-delimited list of one or more server names, e.g. "www1.example.com www2.example.com".
+ * MUST NOT be blank.
+ */
+ public void setServerNames(final String nameList) {
+ CommonUtils.isNotBlank(nameList);
+ this.serverNames = nameList;
+ }
+
+ /** @return The name of the CAS principal attribute that contains role data. */
+ public String getRoleAttribute() {
+ return roleAttribute;
+ }
+
+ /**
+ * Sets the name of the CAS principal attribute that contains role data.
+ *
+ * @param roleAttribute Role attribute name. MUST NOT be blank.
+ */
+ public void setRoleAttribute(final String roleAttribute) {
+ CommonUtils.isNotBlank(roleAttribute);
+ this.roleAttribute = roleAttribute;
+ }
+
+ @Override
+ public void setConfiguration(final AuthConfiguration configuration) {
+ // Nothing to do
+ // All configuration must be via CAS-specific setter methods
+ }
+
+ @Override
+ public String getAuthMethod() {
+ return AUTH_METHOD;
+ }
+
+ @Override
+ public void prepareRequest(final ServletRequest request) {
+ // Nothing to do
+ }
+
+ @Override
+ public Authentication validateRequest(
+ final ServletRequest servletRequest, final ServletResponse servletResponse, final boolean mandatory)
+ throws ServerAuthException {
+
+ final HttpServletRequest request = (HttpServletRequest) servletRequest;
+ final HttpServletResponse response = (HttpServletResponse) servletResponse;
+
+ CasAuthentication authentication = fetchCachedAuthentication(request);
+ if (authentication != null) {
+ return authentication;
+ }
+
+ final String ticket = request.getParameter(protocol.getArtifactParameterName());
+ if (ticket != null && mandatory) {
+ try {
+ logger.debug("Attempting to validate {}", ticket);
+ final Assertion assertion = ticketValidator.validate(ticket, serviceUrl(request, response));
+ logger.info("Successfully authenticated {}", assertion.getPrincipal());
+ authentication = new CasAuthentication(this, ticket, assertion);
+ cacheAuthentication(request, authentication);
+ } catch (Exception e) {
+ throw new ServerAuthException("CAS ticket validation failed", e);
+ }
+ }
+ if (authentication != null) {
+ return authentication;
+ } else if (mandatory) {
+ redirectToCas(request, response);
+ return Authentication.SEND_CONTINUE;
+ }
+ return Authentication.UNAUTHENTICATED;
+ }
+
+ @Override
+ public boolean secureResponse(
+ final ServletRequest request,
+ final ServletResponse response,
+ final boolean mandatory,
+ final Authentication.User user) throws ServerAuthException {
+ return true;
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ if (ticketValidator == null) {
+ throw new RuntimeException("TicketValidator cannot be null");
+ }
+ if (serverNames == null) {
+ throw new RuntimeException("ServerNames cannot be null");
+ }
+ }
+
+ protected void clearCachedAuthentication(final String ticket) {
+ final WeakReference sessionRef = sessionMap.remove(ticket);
+ if (sessionRef != null && sessionRef.get() != null) {
+ sessionRef.get().removeAttribute(CACHED_AUTHN_ATTRIBUTE);
+ }
+ }
+
+ private void cacheAuthentication(final HttpServletRequest request, final CasAuthentication authentication) {
+ final HttpSession session = request.getSession(true);
+ if (session != null) {
+ session.setAttribute(CACHED_AUTHN_ATTRIBUTE, authentication);
+ sessionMap.put(authentication.getTicket(), new WeakReference(session));
+ }
+ }
+
+ private CasAuthentication fetchCachedAuthentication(final HttpServletRequest request) {
+ final HttpSession session = request.getSession(false);
+ if (session != null) {
+ return (CasAuthentication) session.getAttribute(CACHED_AUTHN_ATTRIBUTE);
+ }
+ return null;
+ }
+
+ private String serviceUrl(final HttpServletRequest request, final HttpServletResponse response) {
+ return CommonUtils.constructServiceUrl(
+ request,
+ response,
+ null,
+ serverNames,
+ protocol.getServiceParameterName(),
+ protocol.getArtifactParameterName(),
+ true);
+ }
+
+ private void redirectToCas(
+ final HttpServletRequest request, final HttpServletResponse response) throws ServerAuthException {
+ try {
+ final String redirectUrl = CommonUtils.constructRedirectUrl(
+ casServerLoginUrl, protocol.getServiceParameterName(), serviceUrl(request, response), renew, false);
+ logger.debug("Redirecting to {}", redirectUrl);
+ response.sendRedirect(redirectUrl);
+ } catch (IOException e) {
+ logger.debug("Redirect to CAS failed with error: {}", e);
+ throw new ServerAuthException("Redirect to CAS failed", e);
+ }
+ }
+}
diff --git a/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasUserIdentity.java b/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasUserIdentity.java
new file mode 100644
index 0000000..aee4212
--- /dev/null
+++ b/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasUserIdentity.java
@@ -0,0 +1,67 @@
+package org.jasig.cas.client.jetty;
+
+import org.eclipse.jetty.server.UserIdentity;
+import org.jasig.cas.client.authentication.AttributePrincipal;
+import org.jasig.cas.client.util.CommonUtils;
+import org.jasig.cas.client.validation.Assertion;
+
+import javax.security.auth.Subject;
+import java.security.Principal;
+import java.util.Collection;
+
+/**
+ * CAS user identity backed by assertion data.
+ *
+ * @author Marvin S. Addison
+ */
+public class CasUserIdentity implements UserIdentity {
+
+ /** CAS principal. */
+ private AttributePrincipal principal;
+
+ /** Assertion attribute containing role data. */
+ private String roleAttribute;
+
+
+ /**
+ * Creates a new instance from a CAS assertion containing principal information.
+ *
+ * @param assertion CAS assertion resulting from successful ticket validation.
+ * @param roleAttribute Principal attribute containing role data.
+ */
+ public CasUserIdentity(final Assertion assertion, final String roleAttribute) {
+ CommonUtils.assertNotNull(assertion, "Assertion cannot be null");
+ this.principal = assertion.getPrincipal();
+ this.roleAttribute = roleAttribute;
+ }
+
+ @Override
+ public Subject getSubject() {
+ final Subject subject = new Subject();
+ subject.getPrincipals().add(principal);
+ return subject;
+ }
+
+ @Override
+ public Principal getUserPrincipal() {
+ return principal;
+ }
+
+ @Override
+ public boolean isUserInRole(final String role, final Scope scope) {
+ if (roleAttribute != null) {
+ final Object value = principal.getAttributes().get(roleAttribute);
+ if (value instanceof Collection) {
+ return ((Collection) value).contains(role);
+ } else if (value instanceof String) {
+ return value.equals(role);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return principal.getName();
+ }
+}
diff --git a/cas-client-integration-jetty/src/test/java/org/jasig/cas/client/jetty/CasAuthenticatorTest.java b/cas-client-integration-jetty/src/test/java/org/jasig/cas/client/jetty/CasAuthenticatorTest.java
new file mode 100644
index 0000000..462f353
--- /dev/null
+++ b/cas-client-integration-jetty/src/test/java/org/jasig/cas/client/jetty/CasAuthenticatorTest.java
@@ -0,0 +1,210 @@
+package org.jasig.cas.client.jetty;
+
+import org.apache.tomcat.InstanceManager;
+import org.apache.tomcat.SimpleInstanceManager;
+import org.eclipse.jetty.annotations.ServletContainerInitializersStarter;
+import org.eclipse.jetty.apache.jsp.JettyJasperInitializer;
+import org.eclipse.jetty.jsp.JettyJspServlet;
+import org.eclipse.jetty.plus.annotation.ContainerInitializer;
+import org.eclipse.jetty.security.ConstraintMapping;
+import org.eclipse.jetty.security.ConstraintSecurityHandler;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.util.security.Constraint;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.jasig.cas.client.PublicTestHttpServer;
+import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.CharBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+/**
+ * Unit test for {@link CasAuthenticator}.
+ *
+ * @author Marvin S. Addison
+ */
+public class CasAuthenticatorTest {
+
+ private static final Server server = new Server(8080);
+ private static final CasAuthenticator authenticator = new CasAuthenticator();
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ final WebAppContext context = new WebAppContext();
+ context.setContextPath("/webapp");
+ String workingDir = new File(".").getAbsolutePath();
+ workingDir = workingDir.substring(0, workingDir.length() - 2);
+ final String webappDir;
+ if (workingDir.endsWith("/cas-client-integration-jetty")) {
+ webappDir = workingDir + "/src/test/webapp";
+ } else {
+ webappDir = workingDir + "/cas-client-integration-jetty/src/test/webapp";
+ }
+ context.setWar(webappDir);
+
+
+ // JSP config from https://github.com/jetty-project/embedded-jetty-jsp/
+ System.setProperty("org.apache.jasper.compiler.disablejsr199", "false");
+ context.setAttribute("javax.servlet.context.tempdir", getScratchDir());
+ context.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
+ ".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/.*taglibs.*\\.jar$");
+ context.setAttribute("org.eclipse.jetty.containerInitializers", jspInitializers());
+ context.setAttribute(InstanceManager.class.getName(), new SimpleInstanceManager());
+ context.addBean(new ServletContainerInitializersStarter(context), true);
+ context.addServlet(jspServletHolder(), "*.jsp");
+
+ // Wire up CAS authentication
+ authenticator.setServerNames("localhost:8080");
+ authenticator.setTicketValidator(new Cas20ServiceTicketValidator("http://localhost:8081/cas"));
+
+ // Configure security handling for webapp context
+ final ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
+ final Constraint constraint = new Constraint("CasRealm", Constraint.ANY_AUTH);
+ constraint.setAuthenticate(true);
+ final ConstraintMapping secureMapping = new ConstraintMapping();
+ secureMapping.setPathSpec("/secure.jsp");
+ secureMapping.setConstraint(constraint);
+ securityHandler.addConstraintMapping(secureMapping);
+ securityHandler.setAuthenticator(authenticator);
+ context.setSecurityHandler(securityHandler);
+
+ // Add webapp context and start the server
+ server.setHandler(context);
+ server.start();
+ }
+
+ @Test
+ public void testValidateRequestPublicPageNoTicket() throws Exception {
+ final HttpURLConnection uc = openConnection("http://localhost:8080/webapp/");
+ try {
+ assertEquals(200, uc.getResponseCode());
+ assertTrue(readOutput(uc).contains("Welcome everyone"));
+ } finally {
+ uc.disconnect();
+ }
+ }
+
+ @Test
+ public void testValidateRequestPublicPageWithTicket() throws Exception {
+ final HttpURLConnection uc = openConnection("http://localhost:8080/webapp/?ticket=ST-12345");
+ try {
+ assertEquals(200, uc.getResponseCode());
+ assertTrue(readOutput(uc).contains("Welcome everyone"));
+ } finally {
+ uc.disconnect();
+ }
+ }
+
+ @Test
+ public void testValidateRequestSecurePageNoTicket() throws Exception {
+ final HttpURLConnection uc = openConnection("http://localhost:8080/webapp/secure.jsp");
+ try {
+ assertEquals(302, uc.getResponseCode());
+ assertEquals(
+ "http://localhost:8081/cas/login?service=http%3A%2F%2Flocalhost%3A8080%2Fwebapp%2Fsecure.jsp",
+ uc.getHeaderField("Location"));
+ } finally {
+ uc.disconnect();
+ }
+ }
+
+ @Test
+ public void testValidateRequestSecurePageWithTicket() throws Exception {
+ final String successResponse = "" +
+ "" +
+ "bob" +
+ "" +
+ "";
+ final PublicTestHttpServer server = PublicTestHttpServer.instance(8081);
+ server.content = successResponse.getBytes(StandardCharsets.UTF_8);
+ final HttpURLConnection uc = openConnection("http://localhost:8080/webapp/secure.jsp?ticket=ST-12345");
+ try {
+ assertEquals(200, uc.getResponseCode());
+ assertTrue(readOutput(uc).contains("Hello bob"));
+ } finally {
+ uc.disconnect();
+ }
+ }
+
+ @AfterClass
+ public static void afterClass() throws Exception {
+ server.stop();
+ }
+
+ private String readOutput(final URLConnection connection) throws IOException {
+ final InputStreamReader reader = new InputStreamReader(connection.getInputStream());
+ final StringBuilder builder = new StringBuilder();
+ final CharBuffer buffer = CharBuffer.allocate(1024);
+ try {
+ while (reader.read(buffer) > 0) {
+ builder.append(buffer.flip());
+ buffer.clear();
+ }
+ } finally {
+ reader.close();
+ }
+ return builder.toString();
+ }
+
+ private static File getScratchDir() throws IOException
+ {
+ final File tempDir = new File(System.getProperty("java.io.tmpdir"));
+ final File scratchDir = new File(tempDir.toString(), "embedded-jetty-jsp");
+
+ if (!scratchDir.exists())
+ {
+ if (!scratchDir.mkdirs())
+ {
+ throw new IOException("Unable to create scratch directory: " + scratchDir);
+ }
+ }
+ return scratchDir;
+ }
+
+ /**
+ * Ensure the jsp engine is initialized correctly
+ */
+ private static List jspInitializers()
+ {
+ return Collections.singletonList(new ContainerInitializer(new JettyJasperInitializer(), null));
+ }
+
+ /**
+ * Create JSP Servlet (must be named "jsp")
+ */
+ private static ServletHolder jspServletHolder()
+ {
+ final ServletHolder holderJsp = new ServletHolder("jsp", JettyJspServlet.class);
+ holderJsp.setInitOrder(0);
+ holderJsp.setInitParameter("logVerbosityLevel", "DEBUG");
+ holderJsp.setInitParameter("fork", "false");
+ holderJsp.setInitParameter("xpoweredBy", "false");
+ holderJsp.setInitParameter("compilerTargetVM", "1.7");
+ holderJsp.setInitParameter("compilerSourceVM", "1.7");
+ holderJsp.setInitParameter("keepgenerated", "true");
+ return holderJsp;
+ }
+
+ private static HttpURLConnection openConnection(final String url) throws IOException {
+ final HttpURLConnection uc;
+ try {
+ uc = (HttpURLConnection) new URL(url).openConnection();
+ } catch (IOException e) {
+ throw new RuntimeException("Invalid URL: " + url, e);
+ }
+ uc.setInstanceFollowRedirects(false);
+ uc.connect();
+ return uc;
+ }
+}
\ No newline at end of file
diff --git a/cas-client-integration-jetty/src/test/resources/jetty/context-cas2.xml b/cas-client-integration-jetty/src/test/resources/jetty/context-cas2.xml
new file mode 100644
index 0000000..a786496
--- /dev/null
+++ b/cas-client-integration-jetty/src/test/resources/jetty/context-cas2.xml
@@ -0,0 +1,20 @@
+
+
+
+
+ /
+ /webapps/yourapp
+
+
+
+ app.example.com
+
+
+ https://cas.example.com/cas
+
+
+
+
+
+
+
diff --git a/cas-client-integration-jetty/src/test/resources/jetty/context-saml11.xml b/cas-client-integration-jetty/src/test/resources/jetty/context-saml11.xml
new file mode 100644
index 0000000..5e1d5ad
--- /dev/null
+++ b/cas-client-integration-jetty/src/test/resources/jetty/context-saml11.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ /
+ /webapps/yourapp
+
+
+
+ app.example.com
+ memberOf
+
+
+ https://cas.example.com/cas
+
+
+
+
+
+
+
diff --git a/cas-client-integration-jetty/src/test/webapp/index.jsp b/cas-client-integration-jetty/src/test/webapp/index.jsp
new file mode 100644
index 0000000..6d505bb
--- /dev/null
+++ b/cas-client-integration-jetty/src/test/webapp/index.jsp
@@ -0,0 +1,9 @@
+
+
+
+
+ Welcome Page
+
+Welcome everyone
+
+