com.redblackit.war.AppSecurityHttpTest.java Source code

Java tutorial

Introduction

Here is the source code for com.redblackit.war.AppSecurityHttpTest.java

Source

/*
 * Copyright 2002-2011 the original author or authors, or Red-Black IT Ltd, as appropriate.
 *
 * Licensed 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 com.redblackit.war;

import java.io.IOException;
import java.net.SocketException;

import junit.framework.Assert;

import org.apache.log4j.Logger;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.meterware.httpunit.WebConversation;
import com.meterware.httpunit.WebResponse;

import javax.net.ssl.SSLHandshakeException;

/**
 * @author djnorth
 *         <p/>
 *         Test application security for at http level i.e. before involving
 *         RestTemplate
 *         <p/>
 *         The system property clientAuthMandatory can be used to allow
 *         successful tests with servers such as GlassFish that do not allow
 *         optional client authentication ("want").
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class AppSecurityHttpTest {

    private Logger logger = Logger.getLogger("web.client");

    /**
     * Commonly used attributes from testProperties and messages
     */
    @Value("#{'https://' + testProperties.serverHost + ':' + ( systemProperties['httpsPort.override'] ?: testProperties.httpsPort ) + '/' + testProperties.appPath}")
    private String baseHttpsUrl;
    @Value("#{messages['login.title']}")
    private String loginTitle;
    //@Value("#{systemProperties['clientAuthMandatory'] ?: false}")
    private boolean clientAuthMandatory = false;

    /**
     * setUp with trust store
     */
    @Before
    public void setupClientTrustInfo() {
        System.setProperty("javax.net.ssl.trustStore", "/Users/djnorth/client-keystore.jks");
        System.setProperty("javax.net.ssl.keyStorePassword", "clientpwd");
    }

    /**
     * Test home page to https URL, with valid certificate, but not Spring security user.
     * <p/>
     * We expect the login form to be presented, as the fall-back.
     */
    @Test
    public void testGetHomePageHttpsGoodClientCertNotUser() throws Exception {
        System.setProperty("javax.net.ssl.keyStore", "/Users/djnorth/client2-keystore.jks");
        System.setProperty("javax.net.ssl.keyStorePassword", "client2pwd");
        testGetUrl(baseHttpsUrl, loginTitle, false);
    }

    /**
     * Test home page to https URL, with bad certificate.
     * <p/>
     * We expect the login form to be presented, as the fall-back.
     */
    @Test
    public void testGetHomePageHttpsBadClientCert() throws Exception {
        System.setProperty("javax.net.ssl.keyStore", "/Users/djnorth/untrusted-client-keystore.jks");
        System.setProperty("javax.net.ssl.keyStorePassword", "clientpwd");
        testGetUrl(baseHttpsUrl, loginTitle, true);
    }

    /**
     * Test GET using supplied URL, expectedTitle (to identify login or welcome page), and an indication of whether we
     * should authenticate OK, or not.
     *
     * @param url
     * @param expectedTitle
     * @param badClientCertificate
     * @throws Exception
     */
    private void testGetUrl(final String url, final String expectedTitle, final boolean badClientCertificate)
            throws Exception {
        StringBuilder sb = new StringBuilder();
        sb.append(":url=").append(url).append(":expectedTitle=").append(expectedTitle)
                .append(":badClientCertificate=").append(badClientCertificate).append(":clientAuthMandatory=")
                .append(clientAuthMandatory);
        final String[] spropkeys = { "user.name", "clientAuthMandatory", "javax.net.ssl.keyStore",
                "javax.net.ssl.keyStorePassword", "javax.net.ssl.trustStore", "javax.net.ssl.trustStorePassword" };
        for (String spropkey : spropkeys) {
            sb.append("\n  [").append(spropkey).append("]=").append(System.getProperty(spropkey));
        }

        WebConversation conversation = new WebConversation();
        WebResponse response = null;
        try {
            response = conversation.getResponse(url);
            if (clientAuthMandatory && badClientCertificate) {
                Assert.fail("expected exception for bad certificate:but got response=" + response + sb);
            } else {
                Assert.assertNotNull("response" + sb, response);
                logger.info(response);

                String respUrl = response.getURL().toString();

                Assert.assertTrue("URL should start with '" + baseHttpsUrl + "' ... but was '" + respUrl + "'",
                        respUrl.startsWith(baseHttpsUrl));
                Assert.assertEquals("Title for response page" + sb, expectedTitle, response.getTitle().trim());
            }

        } catch (IOException se) {
            if (clientAuthMandatory && se instanceof SocketException) {
                logger.debug("expected exception" + sb, se);
                Throwable t = se.getCause();
                while (t instanceof SocketException) {
                    t = t.getCause();
                }

                if (t != null) {
                    logger.debug("root cause exception" + sb, t);
                }
            } else {
                logger.fatal("unexpected exception:" + sb, se);
                throw new RuntimeException("unexpected exception" + sb, se);
            }

        }
    }

}