Tomcat valve from P. Pejac

This commit is contained in:
Clément Oudot 2008-07-21 12:00:35 +00:00
parent 898ac4a907
commit 7b4276b6d0
4 changed files with 314 additions and 0 deletions

View File

@ -0,0 +1,81 @@
This valve is only available for tomcat 5.5 or greater
An up2date documentation can be found here:
http://wiki.lemonldap.objectweb.org/xwiki/bin/view/NG/DocAppTomcatValve
COMPILATION
=====================================
Required :
* ant
* jre > 1.4
* tomcat >= 5.5
Configure your tomcat home in build.properties files (be crareful for windosw user ...
path must contains "/" . exemple c:/my hardisk/tomcat/
run ant command.
ValveLemonLDAPNG.jar is created under /dist directory
INSTALLATION
======================================
Copy ValveLemonLDAPNG.jar on <TOMCAT_HOME>/server/lib
Add on your server.xml file a new valve entry like this (in host section) :
<Valve className="org.lemonLDAPNG.SSOValve" userKey="AUTH-USER" roleKey="AUTH-ROLE" roleSeparator="," allows="127.0.0.1"/>
Configure attributes.
userKey : Key in the http header send by lemonLDAP in order to store user login
roleKey : Key in the http header send by lemonLDAP in order to store roles. If lemonLDAP send some roles split by some commas, use
roleSeparator
*roleSeparator : see above
*allows: You can filter remote IP, IP defined in this attributes are allows (use "," separator for multiple IP).
Just set the lemonLDAP on this attribute in order to add more security. If this attribute is missed
all hosts are allowed
(*) Optional attributes
QUICK TEST AN DEBUGGING TIPS
=======================================
Download for exemple probe application (great administration tool for tomcat) http://www.lambdaprobe.org
Install valve and configure it.
Send via lemonLDAP user with role = probeuser ... or other user with role = manager
Probe doesn't ask authentification, you're logged...
For debugging, this valve can print some helpfull information in debug level. Configure logging in tomcat
(see tomcat.apache.org/tomcat-5.5-doc/logging.html )
CONTACT
=======================================
swapon666 (at) users.sourceforge.net

View File

@ -0,0 +1 @@
tomcat.home=C:/Tomcat5.0.28

View File

@ -0,0 +1,56 @@
<project name="valveLemonLDAPNG" default="package.jar">
<property file="${basedir}/build.properties"/>
<property name="app.label" value="${ant.project.name}"/>
<property name="app.jar" value="${app.label}.jar" />
<property name="tomcat.bin" value="${tomcat.home}/bin" />
<property name="tomcat.lib.server" value="${tomcat.home}/server/lib" />
<property name="tomcat.lib.common" value="${tomcat.home}/common/lib" />
<path id="classpath.compilation" >
<fileset dir="${tomcat.bin}">
<include name="*.jar"/>
</fileset>
<fileset dir="${tomcat.lib.server}">
<include name="*.jar"/>
</fileset>
<fileset dir="${tomcat.lib.common}">
<include name="*.jar"/>
</fileset>
</path>
<target name="build" depends="init">
<javac classpathref="classpath.compilation"
srcdir="${basedir}/src"
destdir="${basedir}/build" debug="on"
source="1.5"
target="1.5"
/>
</target>
<target name="init">
<mkdir dir="${basedir}/build"/>
<mkdir dir="${basedir}/dist"/>
</target>
<target name="package.jar" depends="build">
<delete dir="${basedir}/dist"/>
<mkdir dir="${basedir}/dist" />
<jar destfile="${basedir}/dist/${app.jar}"
basedir="${basedir}/build" />
</target>
<target name="clean">
<delete dir="${basedir}/build"/>
<delete dir="${basedir}/dist"/>
</target>
</project>

View File

@ -0,0 +1,176 @@
package org.lemonLDAPNG;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.realm.GenericPrincipal;
import org.apache.catalina.valves.ValveBase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tomcat.util.compat.JdkCompat;
/**
* SSO Valve for lemonLDAPNG
*
*
* @author PEJAC Pascal
*
*/
public class SSOValve extends ValveBase {
private static Log log;
static {
log = LogFactory.getLog(org.lemonLDAPNG.SSOValve.class);
}
private static final JdkCompat jdkCompat = JdkCompat.getJdkCompat();
private static final String info = "org.lemonLDAPNG.SSOValve/1.0";
private String userKey = null;
private String roleKey = null;
private String roleSeparator = null;
boolean flagAllows = false;
// By default allow all hosts
private Pattern allows[] = {Pattern.compile("^.*$")};
public String getInfo() {
return info;
}
public void invoke(Request request, Response response) throws IOException,
ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request
.getRequest();
// get the remote IP
String remoteAdress = request.getRequest().getRemoteAddr();
// check if remote adress is allowed in our list
for (int j = 0; j < allows.length; j++) {
if (log.isDebugEnabled())
log.debug("Pattern "+allows[j].pattern()+" tested on ip remote "+remoteAdress);
if (allows[j].matcher(remoteAdress).matches()) {
List roles = new ArrayList();
// retrieve user and role
String user = httpServletRequest.getHeader(userKey);
String role = httpServletRequest.getHeader(roleKey);
if (log.isDebugEnabled())
log.debug("Processing WebSSO request for "
+ request.getMethod() + " "
+ request.getRequestURI());
if (user != null && role != null) {
if (log.isDebugEnabled())
log.debug("Found data User [ "
+ user + "] with role [ "
+ role+"]");
}
if (roleSeparator != null && role != null) {
String res[] = role.split(roleSeparator);
for (int i = 0; i < res.length; i++) {
roles.add(res[i]);
}
} else {
if (role != null)
roles.add(role);
}
if (user != null) {
request.setUserPrincipal(new GenericPrincipal(this
.getContainer().getRealm(), user, "", roles));
}
getNext().invoke(request, response);
return;
}
}
// error 403 => host not autorized
if (flagAllows) response.sendError(403);
return;
}
/**
* get all pattern from host list
* @param list
* @return
*/
protected Pattern[] precalculate(String list) {
if (list == null)
return new Pattern[0];
list = list.trim();
if (list.length() < 1)
return new Pattern[0];
list = list + ",";
ArrayList reList = new ArrayList();
do {
if (list.length() <= 0)
break;
int comma = list.indexOf(',');
if (comma < 0)
break;
String pattern = list.substring(0, comma).trim();
try {
reList.add(Pattern.compile(pattern));
} catch (PatternSyntaxException e) {
IllegalArgumentException iae = new IllegalArgumentException(sm
.getString("requestFilterValve.syntax", pattern));
jdkCompat.chainException(iae, e);
throw iae;
}
list = list.substring(comma + 1);
} while (true);
Pattern reArray[] = new Pattern[reList.size()];
return (Pattern[]) reList.toArray(reArray);
}
public String getUserKey() {
return userKey;
}
public void setUserKey(String userKey) {
this.userKey = userKey;
if (log.isDebugEnabled() && userKey != null)
log.debug("UserKey [" + this.userKey + "]");
}
public String getRoleKey() {
return roleKey;
}
public void setRoleKey(String roleKey) {
this.roleKey = roleKey;
if (log.isDebugEnabled() && roleKey != null)
log.debug("RoleKey [" + this.roleKey + "]");
}
public String getRoleSeparator() {
return roleSeparator;
}
public void setRoleSeparator(String roleSeparator) {
this.roleSeparator = roleSeparator;
if (log.isDebugEnabled() && roleSeparator != null)
log.debug("RoleSeparator [" + this.roleSeparator + "]");
}
public String getAllows() {
return "";
}
public void setAllows(String allows) {
// override default allows
this.allows = precalculate(allows);
flagAllows = true;
}
}