// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.TimeUnit; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.client.security.Realm; import org.eclipse.jetty.client.security.SimpleRealmResolver; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.security.ConstraintMapping; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.security.authentication.BasicAuthenticator; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.security.Constraint; import org.junit.After; import org.junit.Before; import org.junit.Test; /* ------------------------------------------------------------ */ /** * Functional testing for HttpExchange. */ public class SecurityListenerTest { private Server _server; private int _port; private HttpClient _httpClient; private Realm _jettyRealm; private static final String APP_CONTEXT = "localhost /"; /* ------------------------------------------------------------ */ @Before public void setUp() throws Exception { startServer(); _httpClient=new HttpClient(); _httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); _httpClient.setMaxConnectionsPerAddress(2); _httpClient.start(); _jettyRealm = new Realm() { public String getId() { return "MyRealm"; } public String getPrincipal() { return "jetty"; } public String getCredentials() { return "jetty"; } }; _httpClient.setRealmResolver( new SimpleRealmResolver(_jettyRealm) ); } /* ------------------------------------------------------------ */ @After public void tearDown() throws Exception { stopServer(); _httpClient.stop(); } /* ------------------------------------------------------------ */ // @Test public void xtestPerf() throws Exception { sender(1); Thread.sleep(200); sender(10); Thread.sleep(200); sender(100); Thread.sleep(200); sender(1000); Thread.sleep(200); sender(10000); } /* ------------------------------------------------------------ */ public void sender(final int nb) throws Exception { final CountDownLatch latch=new CountDownLatch(nb); long l0=System.currentTimeMillis(); for (int i=0; i<nb; i++) { final int n=i; if (n%1000==0) { Thread.sleep(200); } HttpExchange httpExchange=new HttpExchange() { @Override protected void onRequestCommitted() { // System.err.println("Request committed"); } @Override protected void onResponseStatus(Buffer version, int status, Buffer reason) { // System.err.println("Response Status: " + version+" "+status+" "+reason); } @Override protected void onResponseHeader(Buffer name, Buffer value) { // System.err.println("Response header: " + name + " = " + value); } @Override protected void onResponseContent(Buffer content) { // System.err.println("Response content:" + content); } @Override protected void onResponseComplete() { // System.err.println("Response completed "+n); latch.countDown(); } }; httpExchange.setURL("http://localhost:"+_port+"/"); httpExchange.addRequestHeader("arbitrary","value"); _httpClient.send(httpExchange); } long last=latch.getCount(); while(last>0) { // System.err.println("waiting for "+last+" sent "+(System.currentTimeMillis()-l0)/1000 + "s ago ..."); latch.await(5,TimeUnit.SECONDS); long next=latch.getCount(); if (last==next) break; last=next; } // System.err.println("missed "+latch.getCount()+" sent "+(System.currentTimeMillis()-l0)/1000 + "s ago."); assertEquals(0,latch.getCount()); long l1=System.currentTimeMillis(); } //TODO jaspi hangs ??? // public void testGetWithContentExchange() throws Exception // { // int i = 1; // // final CyclicBarrier barrier = new CyclicBarrier(2); // ContentExchange httpExchange = new ContentExchange() // { // protected void onResponseComplete() throws IOException // { // super.onResponseComplete(); // try{barrier.await();}catch(Exception e){} // } // }; // httpExchange.setURL("http://localhost:" + _port + "/?i=" + i); // httpExchange.setMethod(HttpMethods.GET); // // _httpClient.send(httpExchange); // // try{barrier.await();}catch(Exception e){} // // } /* ------------------------------------------------------------ */ @Test public void testDestinationSecurityCaching() throws Exception { final CyclicBarrier barrier = new CyclicBarrier(2); ContentExchange httpExchange = new ContentExchange() { @Override protected void onResponseComplete() throws IOException { super.onResponseComplete(); try{barrier.await();}catch(Exception e){} } }; httpExchange.setURL("http://localhost:" + _port + "/?i=1"); httpExchange.setMethod(HttpMethods.GET); _httpClient.send(httpExchange); try{barrier.await();}catch(Exception e){} barrier.reset(); ContentExchange httpExchange2 = new ContentExchange() { @Override protected void onResponseComplete() throws IOException { super.onResponseComplete(); try{barrier.await();}catch(Exception e){} } }; httpExchange2.setURL("http://localhost:" + _port + "/?i=2"); httpExchange2.setMethod(HttpMethods.GET); _httpClient.send(httpExchange2); try{barrier.await();}catch(Exception e){} assertFalse( "exchange was retried", httpExchange2.getRetryStatus() ); } /* ------------------------------------------------------------ */ public static void copyStream(InputStream in, OutputStream out) { try { byte[] buffer=new byte[1024]; int len; while ((len=in.read(buffer))>=0) { out.write(buffer,0,len); } } catch (EofException e) { System.err.println(e); } catch (IOException e) { e.printStackTrace(); } } /* ------------------------------------------------------------ */ private void startServer() throws Exception { _server = new Server(); _server.setGracefulShutdown(500); Connector connector = new SelectChannelConnector(); connector.setPort(0); _server.setConnectors(new Connector[]{connector}); Constraint constraint = new Constraint(); constraint.setName("Need User or Admin"); constraint.setRoles(new String[]{"user", "admin"}); constraint.setAuthenticate(true); ConstraintMapping cm = new ConstraintMapping(); cm.setConstraint(constraint); cm.setPathSpec("/*"); File realmPropFile = MavenTestingUtils.getTestResourceFile("realm.properties"); LoginService loginService = new HashLoginService("MyRealm",realmPropFile.getAbsolutePath()); ConstraintSecurityHandler sh = new ConstraintSecurityHandler(); sh.setLoginService(loginService); sh.setAuthenticator(new BasicAuthenticator()); //ServerAuthentication serverAuthentication = new BasicServerAuthentication(loginService, "MyRealm"); //sh.setServerAuthentication(serverAuthentication); _server.setHandler(sh); Handler testHandler = new AbstractHandler() { public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // System.out.println("passed authentication!"); baseRequest.setHandled(true); response.setStatus(200); if (request.getServerName().equals("jetty.eclipse.org")) { response.getOutputStream().println("Proxy request: "+request.getRequestURL()); } else if (request.getMethod().equalsIgnoreCase("GET")) { response.getOutputStream().println("<hello>"); for (int i=0; i<100; i++) { response.getOutputStream().println(" <world>"+i+"</world>"); if (i%20==0) response.getOutputStream().flush(); } response.getOutputStream().println("</hello>"); } else { copyStream(request.getInputStream(),response.getOutputStream()); } } }; sh.setHandler(testHandler); _server.start(); _port = connector.getLocalPort(); } /* ------------------------------------------------------------ */ private void stopServer() throws Exception { _server.stop(); } }