Java tutorial
/* * JBoss, Home of Professional Open Source. * Copyright 2008, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.as.test.integration.web.formauth; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.cookie.Cookie; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.container.test.api.OperateOnDeployment; import org.jboss.arquillian.container.test.api.RunAsClient; import org.jboss.arquillian.junit.Arquillian; import org.jboss.arquillian.test.api.ArquillianResource; import org.jboss.as.arquillian.api.ServerSetup; import org.jboss.as.arquillian.container.ManagementClient; import org.jboss.as.controller.client.ModelControllerClient; import org.jboss.as.controller.client.OperationBuilder; import org.jboss.as.test.integration.security.common.AbstractSecurityDomainSetup; import org.jboss.dmr.ModelNode; import org.jboss.logging.Logger; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM; import static org.jboss.as.security.Constants.AUTHENTICATION; import static org.jboss.as.security.Constants.CODE; import static org.jboss.as.security.Constants.FLAG; import static org.jboss.as.security.Constants.MODULE_OPTIONS; import static org.jboss.as.security.Constants.SECURITY_DOMAIN; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * Tests of form authentication * * @author Scott.Stark@jboss.org * @author lbarreiro@redhat.com */ @RunWith(Arquillian.class) @RunAsClient @ServerSetup(FormAuthUnitTestCase.FormAuthUnitTestCaseSetup.class) public class FormAuthUnitTestCase { private static Logger log = Logger.getLogger(FormAuthUnitTestCase.class); @ArquillianResource private URL baseURLNoAuth; static class FormAuthUnitTestCaseSetup extends AbstractSecurityDomainSetup { @Override protected String getSecurityDomainName() { return "jbossweb-form-auth"; } @Override public void setup(final ManagementClient managementClient, final String containerId) throws Exception { final List<ModelNode> updates = new ArrayList<ModelNode>(); ModelNode op = new ModelNode(); op.get(OP).set(ADD); op.get(OP_ADDR).add(SUBSYSTEM, "security"); op.get(OP_ADDR).add(SECURITY_DOMAIN, getSecurityDomainName()); ModelNode rolesmodule = new ModelNode(); rolesmodule.get(CODE).set("org.jboss.security.auth.spi.UsersRolesLoginModule"); rolesmodule.get(FLAG).set("required"); rolesmodule.get(MODULE_OPTIONS).add("unauthenticatedIdentity", "nobody"); rolesmodule.get(MODULE_OPTIONS).add("usersProperties", "users.properties"); rolesmodule.get(MODULE_OPTIONS).add("rolesProperties", "roles.properties"); op.get(AUTHENTICATION).set(Arrays.asList(rolesmodule)); updates.add(op); applyUpdates(managementClient.getControllerClient(), updates); } } DefaultHttpClient httpclient = new DefaultHttpClient(); @Deployment(name = "form-auth.war", testable = false) public static WebArchive deployment() { ClassLoader tccl = Thread.currentThread().getContextClassLoader(); String resourcesLocation = "org/jboss/as/test/integration/web/formauth/resources/"; WebArchive war = ShrinkWrap.create(WebArchive.class, "form-auth.war"); war.setWebXML(tccl.getResource(resourcesLocation + "web.xml")); war.addAsWebInfResource(tccl.getResource(resourcesLocation + "jboss-web.xml"), "jboss-web.xml"); war.addClass(SecureServlet.class); war.addClass(SecuredPostServlet.class); war.addClass(LogoutServlet.class); war.addAsWebResource(tccl.getResource(resourcesLocation + "index.html"), "index.html"); war.addAsWebResource(tccl.getResource(resourcesLocation + "unsecure_form.html"), "unsecure_form.html"); war.addAsWebResource(tccl.getResource(resourcesLocation + "restricted/errors.jsp"), "restricted/errors.jsp"); war.addAsWebResource(tccl.getResource(resourcesLocation + "restricted/error.html"), "restricted/error.html"); war.addAsWebResource(tccl.getResource(resourcesLocation + "restricted/login.html"), "restricted/login.html"); log.info(war.toString(true)); return war; } public static void applyUpdates(final List<ModelNode> updates, final ModelControllerClient client) throws Exception { for (ModelNode update : updates) { log.info("+++ Update on " + client + ":\n" + update.toString()); ModelNode result = client.execute(new OperationBuilder(update).build()); if (result.hasDefined("outcome") && "success".equals(result.get("outcome").asString())) { if (result.hasDefined("result")) log.info(result.get("result")); } else if (result.hasDefined("failure-description")) { throw new RuntimeException(result.get("failure-description").toString()); } else { throw new RuntimeException("Operation not successful; outcome = " + result.get("outcome")); } } } /** * Test form authentication of a secured servlet * * @throws Exception */ @Test @Ignore @OperateOnDeployment("form-auth.war") public void testFormAuth() throws Exception { log.info("+++ testFormAuth"); doSecureGetWithLogin("restricted/SecuredServlet"); /* * Access the resource without attempting a login to validate that the * session is valid and that any caching on the server is working as * expected. */ doSecureGet("restricted/SecuredServlet"); } /** * Test that a bad login is redirected to the errors.jsp and that the * session j_exception is not null. */ @Test @Ignore @OperateOnDeployment("form-auth.war") public void testFormAuthException() throws Exception { log.info("+++ testFormAuthException"); URL url = new URL(baseURLNoAuth + "restricted/SecuredServlet"); HttpGet httpget = new HttpGet(url.toURI()); log.info("Executing request " + httpget.getRequestLine()); HttpResponse response = httpclient.execute(httpget); int statusCode = response.getStatusLine().getStatusCode(); Header[] errorHeaders = response.getHeaders("X-NoJException"); assertTrue("Wrong response code: " + statusCode, statusCode == HttpURLConnection.HTTP_OK); assertTrue("X-NoJException(" + Arrays.toString(errorHeaders) + ") is null", errorHeaders.length == 0); HttpEntity entity = response.getEntity(); if ((entity != null) && (entity.getContentLength() > 0)) { String body = EntityUtils.toString(entity); assertTrue("Redirected to login page", body.indexOf("j_security_check") > 0); } else { fail("Empty body in response"); } String sessionID = null; for (Cookie k : httpclient.getCookieStore().getCookies()) { if (k.getName().equalsIgnoreCase("JSESSIONID")) sessionID = k.getValue(); } log.info("Saw JSESSIONID=" + sessionID); // Submit the login form HttpPost formPost = new HttpPost(baseURLNoAuth + "j_security_check"); formPost.addHeader("Referer", baseURLNoAuth + "restricted/login.html"); List<NameValuePair> formparams = new ArrayList<NameValuePair>(); formparams.add(new BasicNameValuePair("j_username", "baduser")); formparams.add(new BasicNameValuePair("j_password", "badpass")); formPost.setEntity(new UrlEncodedFormEntity(formparams, "UTF-8")); log.info("Executing request " + formPost.getRequestLine()); HttpResponse postResponse = httpclient.execute(formPost); statusCode = postResponse.getStatusLine().getStatusCode(); errorHeaders = postResponse.getHeaders("X-NoJException"); assertTrue("Should see HTTP_OK. Got " + statusCode, statusCode == HttpURLConnection.HTTP_OK); assertTrue("X-NoJException(" + Arrays.toString(errorHeaders) + ") is not null", errorHeaders.length != 0); log.debug("Saw X-JException, " + Arrays.toString(errorHeaders)); } /** * Test form authentication of a secured servlet and validate that there is * a SecurityAssociation setting Subject. */ @Test @Ignore @OperateOnDeployment("form-auth.war") public void testFormAuthSubject() throws Exception { log.info("+++ testFormAuthSubject"); doSecureGetWithLogin("restricted/SecuredServlet"); } /** * Test that a post from an unsecured form to a secured servlet does not * loose its data during the redirct to the form login. */ @Test @OperateOnDeployment("form-auth.war") public void testPostDataFormAuth() throws Exception { log.info("+++ testPostDataFormAuth"); URL url = new URL(baseURLNoAuth + "unsecure_form.html"); HttpGet httpget = new HttpGet(url.toURI()); log.info("Executing request " + httpget.getRequestLine()); HttpResponse response = httpclient.execute(httpget); int statusCode = response.getStatusLine().getStatusCode(); Header[] errorHeaders = response.getHeaders("X-NoJException"); assertTrue("Wrong response code: " + statusCode, statusCode == HttpURLConnection.HTTP_OK); assertTrue("X-NoJException(" + Arrays.toString(errorHeaders) + ") is null", errorHeaders.length == 0); EntityUtils.consume(response.getEntity()); // Submit the form to /restricted/SecuredPostServlet HttpPost restrictedPost = new HttpPost(baseURLNoAuth + "restricted/SecuredPostServlet"); List<NameValuePair> restrictedParams = new ArrayList<NameValuePair>(); restrictedParams.add(new BasicNameValuePair("checkParam", "123456")); restrictedPost.setEntity(new UrlEncodedFormEntity(restrictedParams, "UTF-8")); log.info("Executing request " + restrictedPost.getRequestLine()); HttpResponse restrictedResponse = httpclient.execute(restrictedPost); statusCode = restrictedResponse.getStatusLine().getStatusCode(); errorHeaders = restrictedResponse.getHeaders("X-NoJException"); assertTrue("Wrong response code: " + statusCode, statusCode == HttpURLConnection.HTTP_OK); assertTrue("X-NoJException(" + Arrays.toString(errorHeaders) + ") is null", errorHeaders.length == 0); HttpEntity entity = restrictedResponse.getEntity(); if ((entity != null) && (entity.getContentLength() > 0)) { String body = EntityUtils.toString(entity); assertTrue("Redirected to login page", body.indexOf("j_security_check") > 0); } else { fail("Empty body in response"); } String sessionID = null; for (Cookie k : httpclient.getCookieStore().getCookies()) { if (k.getName().equalsIgnoreCase("JSESSIONID")) sessionID = k.getValue(); } log.info("Saw JSESSIONID=" + sessionID); // Submit the login form HttpPost formPost = new HttpPost(baseURLNoAuth + "j_security_check"); formPost.addHeader("Referer", baseURLNoAuth + "restricted/login.html"); List<NameValuePair> formparams = new ArrayList<NameValuePair>(); formparams.add(new BasicNameValuePair("j_username", "user1")); formparams.add(new BasicNameValuePair("j_password", "password1")); formPost.setEntity(new UrlEncodedFormEntity(formparams, "UTF-8")); log.info("Executing request " + formPost.getRequestLine()); HttpResponse postResponse = httpclient.execute(formPost); statusCode = postResponse.getStatusLine().getStatusCode(); errorHeaders = postResponse.getHeaders("X-NoJException"); assertTrue("Should see HTTP_MOVED_TEMP. Got " + statusCode, statusCode == HttpURLConnection.HTTP_MOVED_TEMP); assertTrue("X-NoJException(" + Arrays.toString(errorHeaders) + ") is null", errorHeaders.length == 0); EntityUtils.consume(postResponse.getEntity()); // Follow the redirect to the SecureServlet Header location = postResponse.getFirstHeader("Location"); URL indexURI = new URL(location.getValue()); HttpGet war1Index = new HttpGet(url.toURI()); log.info("Executing request " + war1Index.getRequestLine()); HttpResponse war1Response = httpclient.execute(war1Index); statusCode = war1Response.getStatusLine().getStatusCode(); errorHeaders = war1Response.getHeaders("X-NoJException"); assertTrue("Wrong response code: " + statusCode, statusCode == HttpURLConnection.HTTP_OK); assertTrue("X-NoJException(" + Arrays.toString(errorHeaders) + ") is null", errorHeaders.length == 0); HttpEntity war1Entity = war1Response.getEntity(); if ((war1Entity != null) && (entity.getContentLength() > 0)) { String body = EntityUtils.toString(war1Entity); if (body.indexOf("j_security_check") > 0) fail("Get of " + indexURI + " redirected to login page"); } else { fail("Empty body in response"); } } /** * Test that the war which uses <security-domain * flushOnSessionInvalidation="true"> in the jboss-web.xml does not have any * jaas security domain cache entries after the web session has been * invalidated. */ // lbarerreiro: SKIPPED !!! No JMX connection on AS7 // TODO: Other ways of getting this values !?!? //@Ignore @Test @Ignore public void testFlushOnSessionInvalidation() throws Exception { log.info("+++ testFlushOnSessionInvalidation"); // MBeanServerConnection conn = (MBeanServerConnection) getServer(); // ObjectName name = new // ObjectName("jboss.security:service=JaasSecurityManager"); // JaasSecurityManagerServiceMBean secMgrService = // (JaasSecurityManagerServiceMBean) // MBeanServerInvocationHandler.newProxyInstance(conn, name, // JaasSecurityManagerServiceMBean.class, false); // Access a secured servlet to create a session and jaas cache entry doSecureGetWithLogin("restricted/SecuredServlet"); // Validate that the jaas cache has 1 principal // List<Principal> principals = // secMgrService.getAuthenticationCachePrincipals("jbossweb-form-auth"); // assertTrue("jbossweb-form-auth does not have one and only one principal", // principals.size() == 1); // Logout to clear the cache doSecureGet("Logout"); // principals = // secMgrService.getAuthenticationCachePrincipals("jbossweb-form-auth"); // log.info("jbossweb-form-auth principals = " + // Arrays.toString(principals.toArray())); // assertTrue("jbossweb-form-auth has cached principals", // principals.size() == 0); } public HttpPost doSecureGetWithLogin(String path) throws Exception { return doSecureGetWithLogin(path, "user2", "password2"); } public HttpPost doSecureGetWithLogin(String path, String username, String password) throws Exception { log.info("+++ doSecureGetWithLogin : " + path); URL url = new URL(baseURLNoAuth + path); HttpGet httpget = new HttpGet(url.toURI()); log.info("Executing request " + httpget.getRequestLine()); HttpResponse response = httpclient.execute(httpget); int statusCode = response.getStatusLine().getStatusCode(); Header[] errorHeaders = response.getHeaders("X-NoJException"); assertTrue("Wrong response code: " + statusCode, statusCode == HttpURLConnection.HTTP_OK); assertTrue("X-NoJException(" + Arrays.toString(errorHeaders) + ") is null", errorHeaders.length == 0); HttpEntity entity = response.getEntity(); if ((entity != null) && (entity.getContentLength() > 0)) { String body = EntityUtils.toString(entity); assertTrue("Redirected to login page", body.indexOf("j_security_check") > 0); } else { fail("Empty body in response"); } String sessionID = null; for (Cookie k : httpclient.getCookieStore().getCookies()) { if (k.getName().equalsIgnoreCase("JSESSIONID")) sessionID = k.getValue(); } log.info("Saw JSESSIONID=" + sessionID); // Submit the login form HttpPost formPost = new HttpPost(baseURLNoAuth + "j_security_check"); formPost.addHeader("Referer", baseURLNoAuth + "restricted/login.html"); List<NameValuePair> formparams = new ArrayList<NameValuePair>(); formparams.add(new BasicNameValuePair("j_username", username)); formparams.add(new BasicNameValuePair("j_password", password)); formPost.setEntity(new UrlEncodedFormEntity(formparams, "UTF-8")); log.info("Executing request " + formPost.getRequestLine()); HttpResponse postResponse = httpclient.execute(formPost); statusCode = postResponse.getStatusLine().getStatusCode(); errorHeaders = postResponse.getHeaders("X-NoJException"); assertTrue("Should see HTTP_MOVED_TEMP. Got " + statusCode, statusCode == HttpURLConnection.HTTP_MOVED_TEMP); assertTrue("X-NoJException(" + Arrays.toString(errorHeaders) + ") is null", errorHeaders.length == 0); EntityUtils.consume(postResponse.getEntity()); // Follow the redirect to the SecureServlet Header location = postResponse.getFirstHeader("Location"); URL indexURI = new URL(location.getValue()); HttpGet war1Index = new HttpGet(url.toURI()); log.info("Executing request " + war1Index.getRequestLine()); HttpResponse war1Response = httpclient.execute(war1Index); statusCode = war1Response.getStatusLine().getStatusCode(); errorHeaders = war1Response.getHeaders("X-NoJException"); assertTrue("Wrong response code: " + statusCode, statusCode == HttpURLConnection.HTTP_OK); assertTrue("X-NoJException(" + Arrays.toString(errorHeaders) + ") is null", errorHeaders.length == 0); HttpEntity war1Entity = war1Response.getEntity(); if ((war1Entity != null) && (entity.getContentLength() > 0)) { String body = EntityUtils.toString(war1Entity); if (body.indexOf("j_security_check") > 0) fail("Get of " + indexURI + " redirected to login page"); } else { fail("Empty body in response"); } return formPost; } public void doSecureGet(String path) throws Exception { log.info("+++ doSecureGet : " + path); String sessionID = null; for (Cookie k : httpclient.getCookieStore().getCookies()) { if (k.getName().equalsIgnoreCase("JSESSIONID")) sessionID = k.getValue(); } log.info("Saw JSESSIONID=" + sessionID); URL url = new URL(baseURLNoAuth + path); HttpGet httpget = new HttpGet(url.toURI()); log.info("Executing request" + httpget.getRequestLine()); HttpResponse response = httpclient.execute(httpget); int statusCode = response.getStatusLine().getStatusCode(); Header[] errorHeaders = response.getHeaders("X-NoJException"); assertTrue("Wrong response code: " + statusCode, statusCode == HttpURLConnection.HTTP_OK); assertTrue("X-NoJException(" + Arrays.toString(errorHeaders) + ") is null", errorHeaders.length == 0); } }