Integrating with Jetty

Integration with Jetty can be done in a number of ways.

Integrating with Jetty in Ceptors Distribution

Ceptor contains a built-in Jetty server, which you can use for your own webapps.

Here is a sample launcher xml that starts a demoapp

pp_launch_demoapp.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- Ceptor Launcher configuration -->
<ceptorlauncher port="21311"
	launcherclasspath="classes/launcher;lib/CeptorAgent.jar;extlib/logback-core-1.1.5.jar;extlib/logback-classic-1.1.5.jar;extlib/slf4j-api-1.7.16.jar" jvmstartdelay="10">
    <!-- Ceptor DemoApp -->
    <jvm name="demoapp" vmargs="-Xmx1024M -Xnoclassgc" systemclasspath="">
        <config servers="nios://localhost:21233?validateservercert=false" />
        <classloader name="demoapp" extraclasspath="extlib_extras/jsp">
            <service name="webserver1" launcherclass="dk.itp.managed.service.GenericWarLauncher">
                <property name="registerppsecurityhandler" value="true"/>
                <webserver webapp="${portalprotect.home}/samples/demoapp/PortalProtectDemoApp.war"
                    contextpath="/"
                    bindaddress="0.0.0.0" httpport="8080" sslport="0" minthreads="2" maxthreads="500"
                    maxpostsize="67108864" maxidletime="10000"
                    responseheadersize="32768"
                    outputbuffersize="32768"
                    />
            </service>
        </classloader>
    </jvm>
</ceptorlauncher>

In the above example, the property 

<property name="registerppsecurityhandler" value="true"/>

is all that is required to register the security handler.

Programmatically Install Jetty Security Handler

You can also install the Jetty Security Handler programmatically - Here is a full example, which sets up a security handler, and launches and embedded Jetty Server:

package dk.portalprotect.launcher.demoapp;

import java.io.File;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.security.auth.Subject;
import javax.servlet.ServletRequest;

import dk.itp.security.passticket.Agent;
import dk.itp.security.passticket.PTException;
import org.apache.tomcat.InstanceManager;
import org.apache.tomcat.SimpleInstanceManager;
import org.eclipse.jetty.apache.jsp.JettyJasperInitializer;
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.security.DefaultIdentityService;
import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.webapp.WebAppContext;


/**
 * Bootstrapper, used to start the demoapp using an embedded jetty webserver
 */
public class StartJetty {
	public static class PPPrincipal implements Principal {
		String sessionid;
		
		public PPPrincipal(String sessionid) {
			this.sessionid = sessionid;
		}
		
		public String getName() {
			return sessionid;
		}
		
	}
	
	public static class PPUserIdentity implements UserIdentity {
		Subject subject;
		PPPrincipal principal;
		
		public PPUserIdentity(Subject subject, PPPrincipal principal) {
			this.subject = subject;
			this.principal = principal;
		}

		public Subject getSubject() {
			return subject;
		}

		public Principal getUserPrincipal() {
			return principal;
		}

		public boolean isUserInRole(String role, Scope scope) {
			try {
				boolean member = Agent.getInstance().isMemberOfGroup(principal.sessionid, role);
				if (!member) {
					System.err.println("Warning: User: "+ principal.sessionid + " was not a member of role: " + role);
				}
				return member;
			} catch (PTException e) {
				e.printStackTrace();
				return false;
			}
		}
		
	}
	
	public static class PPLoginService implements LoginService {
		IdentityService identService = new DefaultIdentityService();
		
		public UserIdentity login(String user, Object credentials, ServletRequest request) {
			if (Agent.getInstance().isValid(user)) {
				PPPrincipal principal = new PPPrincipal(user);
				Subject subject = new Subject();
				subject.getPrincipals().add(principal);
				
				return new PPUserIdentity(subject, principal);
				
			}
			return null;
		}
		
		public boolean validate(UserIdentity useridentity) {
			if (useridentity instanceof PPUserIdentity) {
				return Agent.getInstance().isValid(((PPUserIdentity)useridentity).principal.sessionid);
			}
			return false;
		}
		
		public void setIdentityService(IdentityService identityservice) {
			identService = identityservice;
		}
		
		public String getName() {
			return "PortalProtect Security Realm";
		}
		
		public IdentityService getIdentityService() {
			return identService;
		}

		public void logout(UserIdentity useridentity) {
			if (useridentity instanceof PPUserIdentity) {
				try {
					Agent.getInstance().logoff(((PPUserIdentity)useridentity).principal.sessionid);
				} catch (PTException e) {
				}
			}
		}		
	}
	
    private static List<ContainerInitializer> jspInitializers()
    {
        JettyJasperInitializer sci = new JettyJasperInitializer();
        ContainerInitializer initializer = new ContainerInitializer(sci, null);
        List<ContainerInitializer> initializers = new ArrayList<ContainerInitializer>();
        initializers.add(initializer);
        return initializers;
    }
    
	public static void main(String[] arguments) {
		try {
			System.setProperty("org.apache.jasper.compiler.disablejsr199","false");
			
			boolean develop = false;
			int port = 8080;
			for(int i = 0; i < arguments.length; i++) {
				if (arguments[i].equals("-develop"))
					develop = true;
				else if (arguments[i].equals("-port") && i+1 < arguments.length) {
					port = Integer.parseInt(arguments[++i]);
				}
			}
			
			HttpConfiguration httpConfig = new HttpConfiguration();
			httpConfig.setSendServerVersion(false);
			httpConfig.setSendXPoweredBy(false);
			httpConfig.setSendDateHeader(false);
			httpConfig.setResponseHeaderSize(32768);
			httpConfig.setOutputBufferSize(32768);

			final Server srv = new Server();
			ServerConnector con = new ServerConnector(srv, new HttpConnectionFactory(httpConfig));

			con.setPort(port);
			srv.setConnectors(new Connector[] {con});
			
			WebAppContext webapp = new WebAppContext();
			webapp.setContextPath("/");
			webapp.setAttribute("org.eclipse.jetty.containerInitializers", jspInitializers());
			webapp.setAttribute(InstanceManager.class.getName(), new SimpleInstanceManager());
			
			if (develop) {
				webapp.setWar("webapp");
			} else { 
				if (new File("dist/PortalProtectDemoApp.war").exists())
					webapp.setWar("dist/PortalProtectDemoApp.war");
				else
					webapp.setWar("PortalProtectDemoApp.war");
			}
			
			webapp.getSecurityHandler().setLoginService(new PPLoginService());
			webapp.getSessionHandler().getSessionManager().setMaxInactiveInterval(60*60);
			srv.setHandler(webapp);
			srv.start();
			
	        Handler handler = srv.getHandler(); 
	        if(handler instanceof WebAppContext) { 
	            webapp.getSessionHandler().getSessionManager().setMaxInactiveInterval(60*60); // sets to 30 sec 
	        } 
	        
			Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
				public void run() {
					try {
						srv.stop();
					} catch(Throwable t) {
						System.err.println(new Date() + ": Problem shutting down.");
						t.printStackTrace();
					}
				}
			}));

			System.out.println("Jetty now ready on port " + port + " - connect to the demoapp using the PP dispatcher.");
			while(true)
				Thread.sleep(60000);
		} catch (Throwable e) {
			System.err.println("Fatal error starting webserver");
			e.printStackTrace();
		}		
	}	
}


Adding a Security Handler in a Webapp

If you wish, you can also add a security handler directly within your .war file without starting up Jetty yourself.

Simply add a class like this:

Sample Jetty LoginService
package io.ceptor.jetty;

import java.security.Principal;

import javax.security.auth.Subject;
import javax.servlet.ServletRequest;

import org.eclipse.jetty.security.DefaultIdentityService;
import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.server.UserIdentity;

import dk.itp.security.passticket.Agent;
import dk.itp.security.passticket.PTException;

/**
 * Ceptor Jetty Login Service
 */
public class LoginService implements org.eclipse.jetty.security.LoginService {
	public static class PPPrincipal implements Principal {
		String sessionid;

		public PPPrincipal(String sessionid) {
			this.sessionid = sessionid;
		}

		public String getName() {
			return sessionid;
		}

	}

	public static class PPUserIdentity implements UserIdentity {
		Subject subject;
		PPPrincipal principal;

		public PPUserIdentity(Subject subject, PPPrincipal principal) {
			this.subject = subject;
			this.principal = principal;
		}

		public Subject getSubject() {
			return subject;
		}

		public Principal getUserPrincipal() {
			return principal;
		}

		public boolean isUserInRole(String role, Scope scope) {
			try {
				boolean member = Agent.getInstance().isMemberOfGroup(principal.sessionid, role);
				if (!member) {
//					System.err.println("Warning: User: " + principal.sessionid + " was not a member of role: " + role);
				}
				return member;
			} catch (PTException e) {
//				e.printStackTrace();
				return false;
			}
		}

	}

	IdentityService identService = new DefaultIdentityService();

	public UserIdentity login(String username, Object credentials) {
		return login(username, credentials, null);
	}
	
	public UserIdentity login(String user, Object credentials, ServletRequest request) {
		if (Agent.getInstance().isValid(user)) {
			PPPrincipal principal = new PPPrincipal(user);
			Subject subject = new Subject();
			subject.getPrincipals().add(principal);

			return new PPUserIdentity(subject, principal);

		}
		return null;
	}

	public boolean validate(UserIdentity useridentity) {
		if (useridentity instanceof PPUserIdentity) {
			return Agent.getInstance().isValid(((PPUserIdentity) useridentity).principal.sessionid);
		}
		return false;
	}

	public void setIdentityService(IdentityService identityservice) {
		identService = identityservice;
	}

	public String getName() {
		return "Ceptor Security Realm";
	}

	public IdentityService getIdentityService() {
		return identService;
	}

	public void logout(UserIdentity useridentity) {
		if (useridentity instanceof PPUserIdentity) {
			try {
				Agent.getInstance().logoff(((PPUserIdentity) useridentity).principal.sessionid);
			} catch (PTException e) {
			}
		}
	}

}

And then create the following jetty-web.xml in your WEB-INF folder:

Sample jetty-web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty/Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
	<Get name="securityHandler">
		<Set name="loginService"><New class="io.ceptor.jetty.LoginService"></New></Set>
	</Get>
</Configure>

© Ceptor ApS. All Rights Reserved.