Author: markt
Date: Fri Jul 3 19:04:23 2015
New Revision: 1689062
URL: http://svn.apache.org/r1689062
Log:
Port FORM auth unit test for JASPIC
Patch by fjodorver
Added:
tomcat/trunk/test/org/apache/catalina/authenticator/TestJaspicFormAuthenticator.java
(with props)
Added:
tomcat/trunk/test/org/apache/catalina/authenticator/TestJaspicFormAuthenticator.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/authenticator/TestJaspicFormAuthenticator.java?rev=1689062&view=auto
==============================================================================
---
tomcat/trunk/test/org/apache/catalina/authenticator/TestJaspicFormAuthenticator.java
(added)
+++
tomcat/trunk/test/org/apache/catalina/authenticator/TestJaspicFormAuthenticator.java
Fri Jul 3 19:04:23 2015
@@ -0,0 +1,769 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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
+ *
+ * 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.apache.catalina.authenticator;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.security.auth.message.config.AuthConfigFactory;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.authenticator.jaspic.JaspicAuthenticator;
+import
org.apache.catalina.authenticator.jaspic.provider.TomcatAuthConfigProvider;
+import org.apache.catalina.startup.SimpleHttpClient;
+import org.apache.catalina.startup.TesterMapRealm;
+import org.apache.catalina.startup.TesterServlet;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.tomcat.util.descriptor.web.LoginConfig;
+import org.apache.tomcat.util.descriptor.web.SecurityCollection;
+import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
+import org.apache.tomcat.websocket.server.WsContextListener;
+
+/*
+ * Test FORM authentication for sessions that do and do not use cookies.
+ *
+ * 1. A client that can accept and respond to a Set-Cookie for JSESSIONID
+ * will be able to maintain its authenticated session, no matter whether
+ * the session ID is changed once, many times, or not at all.
+ *
+ * 2. A client that cannot accept cookies will only be able to maintain a
+ * persistent session IF the server sends the correct (current) jsessionid
+ * as a path parameter appended to ALL urls within its response. That is
+ * achievable with servlets, jsps, jstl (all of which which can ask for an
+ * encoded url to be inserted into the dynamic web page). It cannot work
+ * with static html.
+ * note: this test class uses the Tomcat sample jsps, which conform.
+ *
+ * 3. Therefore, any webapp that MIGHT need to authenticate a client that
+ * does not accept cookies MUST generate EVERY protected resource url
+ * dynamically (so that it will include the current session ID).
+ *
+ * 4. Any webapp that cannot satisfy case 3 MUST turn off
+ * changeSessionIdOnAuthentication for its Context and thus degrade the
+ * session fixation protection for ALL of its clients.
+ * note from MarkT: Not sure I agree with this. If the URLs aren't
+ * being encoded, then the session is going to break regardless of
+ * whether or not the session ID changes.
+ *
+ * Unlike a "proper browser", this unit test class does a quite lot of
+ * screen-scraping and cheating of headers and urls (not very elegant,
+ * but it makes no claims to generality).
+ *
+ */
+public class TestJaspicFormAuthenticator extends TomcatBaseTest {
+
+ // these should really be singletons to be type-safe,
+ // we are in a unit test and don't need to paranoid.
+ protected static final boolean USE_100_CONTINUE = true;
+ protected static final boolean NO_100_CONTINUE = !USE_100_CONTINUE;
+
+ protected static final boolean CLIENT_USE_COOKIES = true;
+ protected static final boolean CLIENT_NO_COOKIES = !CLIENT_USE_COOKIES;
+
+ protected static final boolean CLIENT_USE_HTTP_11 = true;
+ protected static final boolean CLIENT_USE_HTTP_10 = !CLIENT_USE_HTTP_11;
+
+ protected static final boolean SERVER_USE_COOKIES = true;
+ protected static final boolean SERVER_NO_COOKIES = !SERVER_USE_COOKIES;
+
+ protected static final boolean SERVER_CHANGE_SESSID = true;
+ protected static final boolean SERVER_FREEZE_SESSID =
!SERVER_CHANGE_SESSID;
+
+ // minimum session timeout
+ private static final int TIMEOUT_MINS = 1;
+ private static final long TIMEOUT_DELAY_MSECS = (((TIMEOUT_MINS * 60) +
10) * 1000);
+
+ private FormAuthClient client;
+
+
+ // first, a set of tests where the server uses a cookie to carry
+ // the current session ID during and after authentication, and
+ // the client is prepared to return cookies with each request
+
+ @Test
+ public void testGetWithCookies() throws Exception {
+ doTest("GET", "GET", NO_100_CONTINUE, CLIENT_USE_COOKIES,
SERVER_USE_COOKIES,
+ SERVER_CHANGE_SESSID);
+ }
+
+
+ @Test
+ public void testPostNoContinueWithCookies() throws Exception {
+ doTest("POST", "GET", NO_100_CONTINUE, CLIENT_USE_COOKIES,
SERVER_USE_COOKIES,
+ SERVER_CHANGE_SESSID);
+ }
+
+
+ @Test
+ public void testPostWithContinueAndCookies() throws Exception {
+ doTest("POST", "GET", USE_100_CONTINUE, CLIENT_USE_COOKIES,
SERVER_USE_COOKIES,
+ SERVER_CHANGE_SESSID);
+ }
+
+
+ // Bug 49779
+ @Test
+ public void testPostNoContinuePostRedirectWithCookies() throws Exception {
+ doTest("POST", "POST", NO_100_CONTINUE, CLIENT_USE_COOKIES,
SERVER_USE_COOKIES,
+ SERVER_CHANGE_SESSID);
+ }
+
+
+ // Bug 49779
+ @Test
+ public void testPostWithContinuePostRedirectWithCookies() throws Exception
{
+ doTest("POST", "POST", USE_100_CONTINUE, CLIENT_USE_COOKIES,
SERVER_USE_COOKIES,
+ SERVER_CHANGE_SESSID);
+ }
+
+
+ // next, a set of tests where the server Context is configured to never
+ // use cookies and the session ID is only carried as a url path parameter
+
+ // Bug 53584
+ @Test
+ public void testGetNoServerCookies() throws Exception {
+ doTest("GET", "GET", NO_100_CONTINUE, CLIENT_NO_COOKIES,
SERVER_NO_COOKIES,
+ SERVER_CHANGE_SESSID);
+ }
+
+
+ @Test
+ public void testPostNoContinueNoServerCookies() throws Exception {
+ doTest("POST", "GET", NO_100_CONTINUE, CLIENT_USE_COOKIES,
SERVER_NO_COOKIES,
+ SERVER_CHANGE_SESSID);
+ }
+
+
+ @Test
+ public void testPostWithContinueNoServerCookies() throws Exception {
+ doTest("POST", "GET", USE_100_CONTINUE, CLIENT_USE_COOKIES,
SERVER_NO_COOKIES,
+ SERVER_CHANGE_SESSID);
+ }
+
+
+ // variant of Bug 49779
+ @Test
+ public void testPostNoContinuePostRedirectNoServerCookies() throws
Exception {
+ doTest("POST", "POST", NO_100_CONTINUE, CLIENT_USE_COOKIES,
SERVER_NO_COOKIES,
+ SERVER_CHANGE_SESSID);
+ }
+
+
+ // variant of Bug 49779
+ @Test
+ public void testPostWithContinuePostRedirectNoServerCookies() throws
Exception {
+ doTest("POST", "POST", USE_100_CONTINUE, CLIENT_USE_COOKIES,
SERVER_NO_COOKIES,
+ SERVER_CHANGE_SESSID);
+ }
+
+
+ // next, a set of tests where the server Context uses cookies,
+ // but the client refuses to return them and tries to use
+ // the session ID if carried as a url path parameter
+
+ @Test
+ public void testGetNoClientCookies() throws Exception {
+ doTest("GET", "GET", NO_100_CONTINUE, CLIENT_NO_COOKIES,
SERVER_USE_COOKIES,
+ SERVER_CHANGE_SESSID);
+ }
+
+
+ @Test
+ public void testPostNoContinueNoClientCookies() throws Exception {
+ doTest("POST", "GET", NO_100_CONTINUE, CLIENT_NO_COOKIES,
SERVER_USE_COOKIES,
+ SERVER_CHANGE_SESSID);
+ }
+
+
+ @Test
+ public void testPostWithContinueNoClientCookies() throws Exception {
+ doTest("POST", "GET", USE_100_CONTINUE, CLIENT_NO_COOKIES,
SERVER_USE_COOKIES,
+ SERVER_CHANGE_SESSID);
+ }
+
+
+ // variant of Bug 49779
+ @Test
+ public void testPostNoContinuePostRedirectNoClientCookies() throws
Exception {
+ doTest("POST", "POST", NO_100_CONTINUE, CLIENT_NO_COOKIES,
SERVER_USE_COOKIES,
+ SERVER_CHANGE_SESSID);
+ }
+
+
+ // variant of Bug 49779
+ @Test
+ public void testPostWithContinuePostRedirectNoClientCookies() throws
Exception {
+ doTest("POST", "POST", USE_100_CONTINUE, CLIENT_NO_COOKIES,
SERVER_USE_COOKIES,
+ SERVER_CHANGE_SESSID);
+ }
+
+
+ // finally, a set of tests to explore quirky situations
+ // but there is not need to replicate all the scenarios above.
+
+ @Test
+ public void testNoChangedSessidWithCookies() throws Exception {
+ doTest("GET", "GET", NO_100_CONTINUE, CLIENT_USE_COOKIES,
SERVER_USE_COOKIES,
+ SERVER_FREEZE_SESSID);
+ }
+
+
+ @Test
+ public void testNoChangedSessidWithoutCookies() throws Exception {
+ doTest("GET", "GET", NO_100_CONTINUE, CLIENT_NO_COOKIES,
SERVER_USE_COOKIES,
+ SERVER_FREEZE_SESSID);
+ }
+
+
+ // HTTP 1.0 test
+ @Test
+ public void testGetWithCookiesHttp10() throws Exception {
+ doTest("GET", "GET", NO_100_CONTINUE, CLIENT_USE_COOKIES,
SERVER_USE_COOKIES,
+ SERVER_CHANGE_SESSID, CLIENT_USE_HTTP_10);
+ }
+
+
+ @Test
+ public void doTestSelectedMethods() throws Exception {
+
+ FormAuthClientSelectedMethods client = new
FormAuthClientSelectedMethods(true, true, true,
+ true);
+
+ // First request for protected resource gets the login page
+ client.doResourceRequest("PUT", true, "/test?" +
SelectedMethodsServlet.PARAM + "="
+ + SelectedMethodsServlet.VALUE, null);
+ assertTrue(client.getResponseLine(), client.isResponse200());
+ assertTrue(client.isResponseBodyOK());
+ String originalSessionId = client.getSessionId();
+ client.reset();
+
+ // Second request replies to the login challenge
+ client.doResourceRequest("POST", true, "/test/j_security_check",
+ FormAuthClientBase.LOGIN_REPLY);
+ assertTrue("login failed " + client.getResponseLine(),
client.isResponse303());
+ assertTrue(client.isResponseBodyOK());
+ String redirectUri = client.getRedirectUri();
+ client.reset();
+
+ // Third request - the login was successful so
+ // follow the redirect to the protected resource
+ client.doResourceRequest("GET", true, redirectUri, null);
+ assertTrue(client.isResponse200());
+ assertTrue(client.isResponseBodyOK());
+ String newSessionId = client.getSessionId();
+
+ assertTrue(!originalSessionId.equals(newSessionId));
+ client.reset();
+ }
+
+
+ @Test
+ @Ignore
+ public void testTimeoutWithoutCookies() throws Exception {
+ String protectedUri = doTest("GET", "GET", NO_100_CONTINUE,
CLIENT_NO_COOKIES,
+ SERVER_USE_COOKIES, SERVER_FREEZE_SESSID);
+
+ // wait long enough for my session to expire
+ Thread.sleep(TIMEOUT_DELAY_MSECS);
+
+ // then try to continue using the expired session to get the
+ // protected resource once more.
+ // should get login challenge or timeout status 408
+ doTestProtected("GET", protectedUri, NO_100_CONTINUE,
FormAuthClient.LOGIN_REQUIRED, 1);
+ }
+
+
+ /*
+ * Choreograph the steps of the test dialogue with the server 1. while not
+ * authenticated, try to access a protected resource 2. respond to the
login
+ * challenge with good credentials 3. after successful login, follow the
+ * redirect to the original page 4. repeatedly access the protected
resource
+ * to demonstrate persistence of the authenticated session
+ * @param resourceMethod HTTP method for accessing the protected resource
+ * @param redirectMethod HTTP method for the login FORM reply
+ * @param useContinue whether the HTTP client should expect a 100 Continue
+ * @param clientShouldUseCookies whether the client should send cookies
+ * @param serverWillUseCookies whether the server should send cookies
+ */
+ private String doTest(String resourceMethod, String redirectMethod,
boolean useContinue,
+ boolean clientShouldUseCookies, boolean serverWillUseCookies,
+ boolean serverWillChangeSessid) throws Exception {
+ return doTest(resourceMethod, redirectMethod, useContinue,
clientShouldUseCookies,
+ serverWillUseCookies, serverWillChangeSessid, true);
+ }
+
+
+ private String doTest(String resourceMethod, String redirectMethod,
boolean useContinue,
+ boolean clientShouldUseCookies, boolean serverWillUseCookies,
+ boolean serverWillChangeSessid, boolean clientShouldUseHttp11)
throws Exception {
+
+ client = new FormAuthClient(clientShouldUseCookies,
clientShouldUseHttp11,
+ serverWillUseCookies, serverWillChangeSessid);
+
+ // First request for protected resource gets the login page
+ client.setUseContinue(useContinue);
+ client.doResourceRequest(resourceMethod, false, null, null);
+ assertTrue(client.isResponse200());
+ assertTrue(client.isResponseBodyOK());
+ String loginUri = client.extractBodyUri(FormAuthClient.LOGIN_PARAM_TAG,
+ FormAuthClient.LOGIN_RESOURCE);
+ String originalSessionId = null;
+ if (serverWillUseCookies && clientShouldUseCookies) {
+ originalSessionId = client.getSessionId();
+ } else {
+ originalSessionId = client.extractPathSessionId(loginUri);
+ }
+ client.reset();
+
+ // Second request replies to the login challenge
+ client.setUseContinue(useContinue);
+ client.doLoginRequest(loginUri);
+ if (clientShouldUseHttp11) {
+ assertTrue("login failed " + client.getResponseLine(),
client.isResponse303());
+ } else {
+ assertTrue("login failed " + client.getResponseLine(),
client.isResponse302());
+ }
+ assertTrue(client.isResponseBodyOK());
+ String redirectUri = client.getRedirectUri();
+ client.reset();
+
+ // Third request - the login was successful so
+ // follow the redirect to the protected resource
+ client.doResourceRequest(redirectMethod, true, redirectUri, null);
+ if ("POST".equals(redirectMethod)) {
+ client.setUseContinue(useContinue);
+ }
+ assertTrue(client.isResponse200());
+ assertTrue(client.isResponseBodyOK());
+ String protectedUri =
client.extractBodyUri(FormAuthClient.RESOURCE_PARAM_TAG,
+ FormAuthClient.PROTECTED_RESOURCE);
+ String newSessionId = null;
+ if (serverWillUseCookies && clientShouldUseCookies) {
+ newSessionId = client.getSessionId();
+ } else {
+ newSessionId = client.extractPathSessionId(protectedUri);
+ }
+ boolean sessionIdIsChanged = !(originalSessionId.equals(newSessionId));
+ // TODO implement this option
+ // assertTrue(sessionIdIsChanged == serverWillChangeSessid);
+ client.reset();
+
+ // Subsequent requests - keep accessing the protected resource
+ doTestProtected(resourceMethod, protectedUri, useContinue,
FormAuthClient.LOGIN_SUCCESSFUL,
+ 5);
+
+ return protectedUri; // in case more requests will be issued
+ }
+
+
+ /*
+ * Repeatedly access the protected resource after the client has
+ * successfully logged-in to the webapp. The current session attributes
will
+ * be used and cannot be changed. 3. after successful login, follow the
+ * redirect to the original page 4. repeatedly access the protected
resource
+ * to demonstrate persistence of the authenticated session
+ * @param resourceMethod HTTP method for accessing the protected resource
+ * @param protectedUri to access (with or without sessionid)
+ * @param useContinue whether the HTTP client should expect a 100 Continue
+ * @param clientShouldUseCookies whether the client should send cookies
+ * @param serverWillUseCookies whether the server should send cookies
+ */
+ private void doTestProtected(String resourceMethod, String protectedUri,
boolean useContinue,
+ int phase, int repeatCount) throws Exception {
+
+ // Subsequent requests - keep accessing the protected resource
+ for (int i = 0; i < repeatCount; i++) {
+ client.setUseContinue(useContinue);
+ client.doResourceRequest(resourceMethod, false, protectedUri,
null);
+ assertTrue(client.isResponse200());
+ assertTrue(client.isResponseBodyOK(phase));
+ client.reset();
+ }
+ }
+
+ /*
+ * Encapsulate the logic needed to run a suitably-configured tomcat
+ * instance, send it an HTTP request and process the server response
+ */
+ private abstract class FormAuthClientBase extends SimpleHttpClient {
+
+ protected static final String LOGIN_PARAM_TAG = "action=";
+ protected static final String LOGIN_RESOURCE = "j_security_check";
+ protected static final String LOGIN_REPLY =
"j_username=tomcat&j_password=tomcat";
+
+ protected static final String PROTECTED_RELATIVE_PATH =
"/examples/jsp/security/protected/";
+ protected static final String PROTECTED_RESOURCE = "index.jsp";
+ private static final String PROTECTED_RESOURCE_URL =
PROTECTED_RELATIVE_PATH
+ + PROTECTED_RESOURCE;
+ protected static final String RESOURCE_PARAM_TAG = "href=";
+ private static final char PARAM_DELIM = '?';
+
+ // primitive tracking of the test phases to verify the HTML body
+ protected static final int LOGIN_REQUIRED = 1;
+ protected static final int REDIRECTING = 2;
+ protected static final int LOGIN_SUCCESSFUL = 3;
+ private int requestCount = 0;
+
+ // todo: forgot this change and making it up again!
+ protected final String SESSION_PARAMETER_START =
SESSION_PARAMETER_NAME + "=";
+
+ protected boolean clientShouldUseHttp11;
+
+
+ protected void doLoginRequest(String loginUri) throws Exception {
+
+ doResourceRequest("POST", true, PROTECTED_RELATIVE_PATH +
loginUri, LOGIN_REPLY);
+ }
+
+
+ /*
+ * Prepare the resource request HTTP headers and issue the request.
+ * Three kinds of uri are supported: 1. fully qualified uri. 2. minimal
+ * uri without webapp path. 3. null - use the default protected
resource
+ * Cookies are sent if available and supported by the test. Otherwise,
+ * the caller is expected to have provided a session id as a path
+ * parameter.
+ */
+ protected void doResourceRequest(String method, boolean isFullQualUri,
String resourceUri,
+ String requestTail) throws Exception {
+
+ // build the HTTP request while assembling the uri
+ StringBuilder requestHead = new StringBuilder(128);
+ requestHead.append(method).append(" ");
+ if (isFullQualUri) {
+ requestHead.append(resourceUri);
+ } else {
+ if (resourceUri == null) {
+ // the default relative url
+ requestHead.append(PROTECTED_RESOURCE_URL);
+ } else {
+
requestHead.append(PROTECTED_RELATIVE_PATH).append(resourceUri);
+ }
+ if ("GET".equals(method)) {
+ requestHead.append("?role=bar");
+ }
+ }
+ if (clientShouldUseHttp11) {
+ requestHead.append(" HTTP/1.1").append(CRLF);
+ } else {
+ requestHead.append(" HTTP/1.0").append(CRLF);
+ }
+
+ // next, add the constant http headers
+ requestHead.append("Host: localhost").append(CRLF);
+ requestHead.append("Connection: close").append(CRLF);
+
+ // then any optional http headers
+ if (getUseContinue()) {
+ requestHead.append("Expect: 100-continue").append(CRLF);
+ }
+ if (getUseCookies()) {
+ String sessionId = getSessionId();
+ if (sessionId != null) {
+ requestHead.append("Cookie:
").append(SESSION_COOKIE_NAME).append("=")
+ .append(sessionId).append(CRLF);
+ }
+ }
+
+ // finally, for posts only, deal with the request content
+ if ("POST".equals(method)) {
+ if (requestTail == null) {
+ requestTail = "role=bar";
+ }
+ requestHead.append("Content-Type:
application/x-www-form-urlencoded").append(CRLF);
+ // calculate post data length
+ String len = Integer.toString(requestTail.length());
+ requestHead.append("Content-length:
").append(len).append(CRLF);
+ }
+
+ // always put an empty line after the headers
+ requestHead.append(CRLF);
+
+ String request[] = new String[2];
+ request[0] = requestHead.toString();
+ request[1] = requestTail;
+ doRequest(request);
+ }
+
+
+ private void doRequest(String request[]) throws Exception {
+ setRequest(request);
+ connect();
+ processRequest();
+ disconnect();
+ requestCount++;
+ }
+
+
+ /*
+ * verify the server response html body is the page we expect, based on
+ * the dialogue position within doTest.
+ */
+ @Override
+ public boolean isResponseBodyOK() {
+ return isResponseBodyOK(requestCount);
+ }
+
+
+ /*
+ * verify the server response html body is the page we expect, based on
+ * the dialogue position given by the caller.
+ */
+ public boolean isResponseBodyOK(int testPhase) {
+ switch (testPhase) {
+ case LOGIN_REQUIRED:
+ // First request should return in the login page
+ assertContains(getResponseBody(), "<title>Login Page for
Examples</title>");
+ return true;
+ case REDIRECTING:
+ // Second request should result in redirect without a body
+ return true;
+ default:
+ // Subsequent requests should return in the protected page.
+ // Our role parameter should be appear in the page.
+ String body = getResponseBody();
+ assertContains(body, "<title>Protected Page for
Examples</title>");
+ assertContains(body, "<input type=\"text\" name=\"role\"
value=\"bar\"");
+ return true;
+ }
+ }
+
+
+ /*
+ * Scan the server response body and extract the given url, including
+ * any path elements.
+ */
+ protected String extractBodyUri(String paramTag, String resource) {
+ extractUriElements();
+ List<String> elements = getResponseBodyUriElements();
+ String fullPath = null;
+ for (String element : elements) {
+ int ix = element.indexOf(paramTag);
+ if (ix > -1) {
+ ix += paramTag.length();
+ char delim = element.charAt(ix);
+ int iy = element.indexOf(resource, ix);
+ if (iy > -1) {
+ int lastCharIx = element.indexOf(delim, iy);
+ fullPath = element.substring(iy, lastCharIx);
+ // remove any trailing parameters
+ int paramDelim = fullPath.indexOf(PARAM_DELIM);
+ if (paramDelim > -1) {
+ fullPath = fullPath.substring(0, paramDelim);
+ }
+ break;
+ }
+ }
+ }
+ return fullPath;
+ }
+
+
+ /*
+ * extract the session id path element (if it exists in the given url)
+ */
+ protected String extractPathSessionId(String url) {
+ String sessionId = null;
+ int iStart = url.indexOf(SESSION_PARAMETER_START);
+ if (iStart > -1) {
+ iStart += SESSION_PARAMETER_START.length();
+ String remainder = url.substring(iStart);
+ StringTokenizer parser = new StringTokenizer(remainder,
+ SESSION_PATH_PARAMETER_TAILS);
+ if (parser.hasMoreElements()) {
+ sessionId = parser.nextToken();
+ } else {
+ sessionId = url.substring(iStart);
+ }
+ }
+ return sessionId;
+ }
+
+
+ private void assertContains(String body, String expected) {
+ if (!body.contains(expected)) {
+ fail("Response number " + requestCount + ": body check
failure.\n"
+ + "Expected to contain substring: [" + expected +
"]\nActual: [" + body
+ + "]");
+ }
+ }
+ }
+
+ private class FormAuthClient extends FormAuthClientBase {
+ private FormAuthClient(boolean clientShouldUseCookies, boolean
clientShouldUseHttp11,
+ boolean serverShouldUseCookies, boolean
serverShouldChangeSessid) throws Exception {
+
+ this.clientShouldUseHttp11 = clientShouldUseHttp11;
+
+ Tomcat tomcat = getTomcatInstance();
+ File appDir = new File(getBuildDirectory(), "webapps/examples");
+ Context ctx = tomcat.addWebapp(null, "/examples",
appDir.getAbsolutePath());
+ setUseCookies(clientShouldUseCookies);
+ ctx.setCookies(serverShouldUseCookies);
+ ctx.addApplicationListener(WsContextListener.class.getName());
+
+ TesterMapRealm realm = new TesterMapRealm();
+ realm.addUser("tomcat", "tomcat");
+ realm.addUserRole("tomcat", "tomcat");
+ ctx.setRealm(realm);
+
+ AuthConfigFactory authConfigFactory =
AuthConfigFactory.getFactory();
+ TomcatAuthConfigProvider provider = new
TomcatAuthConfigProvider(ctx);
+ authConfigFactory.registerConfigProvider(provider,
JaspicAuthenticator.MESSAGE_LAYER,
+ null, "Tomcat Jaspic");
+ ctx.getPipeline().addValve(new JaspicAuthenticator());
+
+ tomcat.start();
+
+ // perhaps this does not work until tomcat has started?
+ ctx.setSessionTimeout(TIMEOUT_MINS);
+
+ // Port only known after Tomcat starts
+ setPort(getPort());
+ }
+ }
+
+ /**
+ * Encapsulate the logic needed to run a suitably-configured Tomcat
+ * instance, send it an HTTP request and process the server response when
+ * the protected resource is only protected for some HTTP methods. The use
+ * case of particular interest is when GET and POST are not protected since
+ * those are the methods used by the login form and the redirect and if
+ * those methods are not protected the authenticator may not process the
+ * associated requests.
+ */
+ private class FormAuthClientSelectedMethods extends FormAuthClientBase {
+
+ private FormAuthClientSelectedMethods(boolean clientShouldUseCookies,
+ boolean clientShouldUseHttp11, boolean serverShouldUseCookies,
+ boolean serverShouldChangeSessid) throws Exception {
+
+ this.clientShouldUseHttp11 = clientShouldUseHttp11;
+
+ Tomcat tomcat = getTomcatInstance();
+
+ Context ctx = tomcat.addContext("",
System.getProperty("java.io.tmpdir"));
+ Tomcat.addServlet(ctx, "SelectedMethods", new
SelectedMethodsServlet());
+ ctx.addServletMapping("/test", "SelectedMethods");
+ // Login servlet just needs to respond "OK". Client will handle
+ // creating a valid response. No need for a form.
+ Tomcat.addServlet(ctx, "Login", new TesterServlet());
+ ctx.addServletMapping("/login", "Login");
+
+ // Configure the security constraints
+ SecurityConstraint constraint = new SecurityConstraint();
+ SecurityCollection collection = new SecurityCollection();
+ collection.setName("Protect PUT");
+ collection.addMethod("PUT");
+ collection.addPattern("/test");
+ constraint.addCollection(collection);
+ constraint.addAuthRole("tomcat");
+ ctx.addConstraint(constraint);
+
+ // Configure authentication
+ LoginConfig lc = new LoginConfig();
+ lc.setAuthMethod("JASPIC-FORM");
+ lc.setLoginPage("/login");
+ ctx.setLoginConfig(lc);
+ ctx.getPipeline().addValve(new FormAuthenticator());
+
+ setUseCookies(clientShouldUseCookies);
+ ctx.setCookies(serverShouldUseCookies);
+
+ TesterMapRealm realm = new TesterMapRealm();
+ realm.addUser("tomcat", "tomcat");
+ realm.addUserRole("tomcat", "tomcat");
+ ctx.setRealm(realm);
+
+ AuthConfigFactory authConfigFactory =
AuthConfigFactory.getFactory();
+ TomcatAuthConfigProvider provider = new
TomcatAuthConfigProvider(ctx);
+ authConfigFactory.registerConfigProvider(provider,
JaspicAuthenticator.MESSAGE_LAYER,
+ null, "Tomcat Jaspic");
+ ctx.getPipeline().addValve(new JaspicAuthenticator());
+
+ tomcat.start();
+
+ // perhaps this does not work until tomcat has started?
+ ctx.setSessionTimeout(TIMEOUT_MINS);
+
+ // Port only known after Tomcat starts
+ setPort(getPort());
+ }
+
+
+ @Override
+ public boolean isResponseBodyOK() {
+ if (isResponse303()) {
+ return true;
+ }
+ assertTrue(getResponseBody(), getResponseBody().contains("OK"));
+ assertFalse(getResponseBody().contains("FAIL"));
+ return true;
+ }
+ }
+
+ private static final class SelectedMethodsServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+ public static final String PARAM = "TestParam";
+ public static final String VALUE = "TestValue";
+
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ resp.setContentType("text/plain;charset=UTF-8");
+
+ if (VALUE.equals(req.getParameter(PARAM)) &&
req.isUserInRole("tomcat")) {
+ resp.getWriter().print("OK");
+ } else {
+ resp.getWriter().print("FAIL");
+ }
+ }
+
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Same as GET for this test case
+ doGet(req, resp);
+ }
+
+
+ @Override
+ protected void doPut(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Same as GET for this test case
+ doGet(req, resp);
+ }
+ }
+}
Propchange:
tomcat/trunk/test/org/apache/catalina/authenticator/TestJaspicFormAuthenticator.java
------------------------------------------------------------------------------
svn:eol-style = native
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]