org.qi4j.library.shiro.web.WebRealmServiceTest.java Source code

Java tutorial

Introduction

Here is the source code for org.qi4j.library.shiro.web.WebRealmServiceTest.java

Source

/*
 * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
 *
 * 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 org.qi4j.library.shiro.web;

import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.AuthState;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.apache.shiro.authc.credential.DefaultPasswordService;
import org.apache.shiro.authc.credential.PasswordMatcher;
import org.apache.shiro.authc.credential.PasswordService;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.junit.Test;
import org.qi4j.api.mixin.Mixins;
import org.qi4j.api.service.ServiceActivation;
import org.qi4j.api.service.ServiceComposite;
import org.qi4j.bootstrap.AssemblyException;
import org.qi4j.bootstrap.ModuleAssembly;
import org.qi4j.library.http.JettyConfiguration;
import org.qi4j.library.http.JettyServiceAssembler;
import org.qi4j.library.shiro.ini.ShiroIniConfiguration;
import org.qi4j.library.shiro.web.assembly.HttpShiroAssembler;
import org.qi4j.test.AbstractQi4jTest;
import org.qi4j.test.EntityTestAssembler;
import org.qi4j.test.util.FreePortFinder;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.qi4j.library.http.Servlets.addServlets;
import static org.qi4j.library.http.Servlets.serve;

public class WebRealmServiceTest extends AbstractQi4jTest {

    private int port;

    @Mixins(MyRealmMixin.class)
    public interface MyRealmService extends Realm, ServiceComposite, ServiceActivation {
    }

    public class MyRealmMixin extends SimpleAccountRealm implements ServiceActivation {

        private final PasswordService passwordService;

        public MyRealmMixin() {
            super();
            passwordService = new DefaultPasswordService();
            PasswordMatcher matcher = new PasswordMatcher();
            matcher.setPasswordService(passwordService);
            setCredentialsMatcher(matcher);
        }

        public void activateService() throws Exception {
            // Create a test account
            addAccount("foo", passwordService.encryptPassword("bar"));
        }

        public void passivateService() throws Exception {
        }

    }

    @Mixins(MyServlet.class)
    public interface MyServletService extends Servlet, ServiceComposite {
    }

    public static class MyServlet extends HttpServlet {

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            resp.getWriter().println("FOO");
        }

    }

    @Override
    public void assemble(ModuleAssembly module) throws AssemblyException {
        try {

            new EntityTestAssembler().assemble(module);
            ModuleAssembly configModule = module;
            // START SNIPPET: assembly
            new JettyServiceAssembler().assemble(module);
            // END SNIPPET: assembly

            port = FreePortFinder.findFreePortOnLoopback();
            JettyConfiguration config = module.forMixin(JettyConfiguration.class).declareDefaults();
            config.hostName().set("127.0.0.1");
            config.port().set(port);

            // START SNIPPET: assembly
            new HttpShiroAssembler().withConfig(configModule).assemble(module);
            module.services(MyRealmService.class);
            // END SNIPPET: assembly

            configModule.forMixin(ShiroIniConfiguration.class).declareDefaults().iniResourcePath()
                    .set("classpath:web-shiro.ini");

            addServlets(serve("/*").with(MyServletService.class)).to(module);

        } catch (IOException ex) {
            throw new AssemblyException("Unable to find free port to bind to", ex);
        }
    }

    @Test
    public void test() throws IOException {
        DefaultHttpClient client = new DefaultHttpClient();

        // Our request method
        HttpGet get = new HttpGet("http://127.0.0.1:" + port + "/");

        HttpResponse response = client.execute(get);
        int status = response.getStatusLine().getStatusCode();

        assertThat(String.valueOf(status).substring(0, 1) + "xx", is("4xx"));

        EntityUtils.consume(response.getEntity());

        // Simple interceptor set as first interceptor in the protocol chain
        HttpRequestInterceptor preemptiveAuth = new BasicAuthRequestInterceptor();
        client.addRequestInterceptor(preemptiveAuth, 0);

        // Set credentials
        UsernamePasswordCredentials creds = new UsernamePasswordCredentials("foo", "bar");
        client.getCredentialsProvider().setCredentials(AuthScope.ANY, creds);

        response = client.execute(get);
        status = response.getStatusLine().getStatusCode();

        assertThat(status, is(200));

        String result = new BasicResponseHandler().handleResponse(response).trim();
        assertThat(result, is("FOO"));
    }

    /**
     * HttpClient Basic Auth Request Interceptor.
     * Needed for HTTP Basic Authentication.
     */
    public class BasicAuthRequestInterceptor implements HttpRequestInterceptor {

        public void process(final HttpRequest request, final HttpContext context)
                throws HttpException, IOException {

            AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
            CredentialsProvider credsProvider = (CredentialsProvider) context
                    .getAttribute(ClientContext.CREDS_PROVIDER);
            HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);

            // If not auth scheme has been initialized yet
            if (authState.getAuthScheme() == null) {
                AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());
                // Obtain credentials matching the target host
                Credentials creds = credsProvider.getCredentials(authScope);
                // If found, generate BasicScheme preemptively
                if (creds != null) {
                    authState.setAuthScheme(new BasicScheme());
                    authState.setCredentials(creds);
                }
            }
        }

    }

}