|
What this is
Other links
The source codepackage org.apache.tomcat.j2ee; import javax.servlet.*; import javax.servlet.http.*; import org.apache.tomcat.core.*; import com.sun.web.server.*; import com.sun.enterprise.util.JarClassLoader; import java.net.URL; import java.net.InetAddress; import java.io.File; import java.io.IOException; import java.security.Principal; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; import javax.net.ssl.*; import javax.security.cert.X509Certificate; import com.sun.enterprise.util.*; import com.sun.enterprise.*; import com.sun.enterprise.security.*; import com.sun.enterprise.security.acl.*; import com.sun.enterprise.log.*; import com.sun.enterprise.deployment.WebBundleDescriptor; import org.apache.tomcat.deployment.*; import org.apache.tomcat.util.*; // depends on servlet 2.2 import org.apache.tomcat.facade.*; import org.apache.tomcat.helper.*; /** * Adapter for j2ee. * * @author Harish Prabandham * @author Costin Manolache */ public class J2EEInterceptor extends BaseInterceptor { InvocationManagerImpl invM; private static LocalStringManagerImpl localStrings; private static ServerConfiguration config; private Hashtable accessLogs = new Hashtable(); private Hashtable errorLogs = new Hashtable(); private static final String HTTP_ACCESS_LOG = "web.access.log"; private static final String HTTP_ERROR_LOG = "web.error.log"; private static final int BUFFER_SIZE = 1024; int userNote; int passwordNote; // auth private static int MAX_COUNT = 5; private static int SLEEP_TIME = 5000; // milliseconds.... public J2EEInterceptor() { this.invM= (InvocationManagerImpl) Switch.getSwitch(). getInvocationManager(); config= ServerConfiguration.getConfiguration(); // minimize the changes in j2ee ( temp, until properties are moved) localStrings = new LocalStringManagerImpl(com.sun.web.security.DataConstraint.class); } public void engineInit( ContextManager cm ) throws TomcatException { super.engineInit(cm); userNote=cm.getNoteId( ContextManager.REQUEST_NOTE, "credentials.user"); passwordNote=cm.getNoteId( ContextManager.REQUEST_NOTE, "credentials.password"); debug=10; } public void contextInit( Context ctx) throws TomcatException { } public int preService(Request request, Response response) { Context ctx = request.getContext(); Handler sw=request.getHandler(); if( ! (sw instanceof ServletHandler) ) return 0; try { invM.preServletInvoke( (ServletContext)ctx.getFacade(), ((ServletHandler)sw).getServlet(), (HttpServletRequest)request.getFacade(), (HttpServletResponse)response.getFacade() ); } catch(Exception ex ) { return -1; } return 0; } public int postService(Request request, Response response) { Context ctx = request.getContext(); Handler sw=request.getHandler(); if( ! (sw instanceof ServletHandler) ) return 0; try { invM.postServletInvoke( (ServletContext)ctx.getFacade(), ((ServletHandler)sw).getServlet(), (HttpServletRequest)request.getFacade(), (HttpServletResponse)response.getFacade()); intLogRequest( request.getContext().getPath(), request.requestURI().toString(), null); } catch(Exception ex ) { return -1; } return 0; } /** Servlet Init notification */ public void preServletInit( Context ctx, Handler sw ) throws TomcatException { if( ! (sw instanceof ServletHandler) ) return; try { invM.preInitInvoke( (ServletContext)ctx.getFacade(), ((ServletHandler)sw).getServlet()); } catch(Exception ex ) { log("XXX " + invM + " " + ctx + " " + sw ); throw new TomcatException( "Error in j2ee adapter " , ex ); } } public void postServletInit( Context ctx, Handler sw ) throws TomcatException { if( ! (sw instanceof ServletHandler) ) return; try { invM.postInitInvoke( (ServletContext)ctx.getFacade(), ((ServletHandler)sw).getServlet()); } catch(Exception ex ) { throw new TomcatException( "Error in j2ee adapter " , ex ); } } /** Servlet Destroy notification */ public void preServletDestroy( Context ctx, Handler sw ) throws TomcatException { if( ! (sw instanceof ServletHandler) ) return; try { if( sw != null && ctx != null ) invM.preDestroyInvoke( (ServletContext)ctx.getFacade(), ((ServletHandler)sw).getServlet()); else log("XXX J2EEInterceptor: sw, ctx=" + sw + " " +ctx); } catch(Exception ex ) { ex.printStackTrace(); throw new TomcatException( "Error in j2ee adapter " , ex ); } } public void postServletDestroy( Context ctx, Handler sw ) throws TomcatException { if( ! (sw instanceof ServletHandler) ) return; try { if( sw != null && ctx != null ) invM.postDestroyInvoke( (ServletContext)ctx.getFacade(), ((ServletHandler)sw).getServlet()); else log("XXX J2EEInterceptor: sw, ctx=" + sw + " " +ctx); } catch(Exception ex ) { throw new TomcatException( "Error in j2ee adapter " , ex ); } } // -------------------- Authentication hooks -------------------- public int authenticate( Request req, Response res ) { Context ctx=req.getContext(); // This realm will use only username and password callbacks String user=(String)req.getNote( userNote ); String password=(String)req.getNote( passwordNote );; if( debug>0 ) log( "Try to auth " + user + " " + password); if( user==null || password == null ) { // Need auth, but have no user/pass return DECLINED; } byte authData[]=password.getBytes(); String realm="default"; //ctx.getRealmName(); String authM=null;// ctx.getAuthMethod(); LoginContext lc = initLoginContext(realm); if( lc==null ) { log("Authenticate - Can't get LoginContext...."); return DECLINED; } if(authM != null) lc.setAuthenticationMethod(authM); SecurityContext.setCurrent(null); try { lc.login(user,authData); } catch (LoginException le) { // Log the information here // le.printStackTrace(); Log.err.println(le); //le.printStackTrace(); log("Login failed for..: " + user); return DECLINED; // or 401 ? } if(debug>0) { log("Login succeeded for..: " + user); } req.setRemoteUser( user ); req.setUserPrincipal( getUserPrincipal() ); return OK; } public int authorize( Request req, Response response, String roles[] ) { if( roles==null || roles.length==0 ) { return OK; } Context ctx=req.getContext(); WebBundleDescriptor wbd = (WebBundleDescriptor) Switch.getSwitch().getDescriptorFor(ctx.getFacade()); String appName="default"; if(wbd != null) appName=wbd.getApplication().getName(); if( debug>0) log("appname=" + appName); // call back the authenticate hooks String user=req.getRemoteUser(); if( user==null ) { // Need auth, but have no user/pass if( debug>0) log("no username"); return DECLINED; } String userRoles[]=null; String realm="default"; //ctx.getRealmName(); Handler h=req.getHandler(); ServletHandler sw=(ServletHandler)h; String mappedRole=null; String role=null; for( int i=0; i< roles.length ; i++ ) { role=roles[i]; mappedRole=sw.getServletInfo().getSecurityRole( role ); if( mappedRole==null) mappedRole=role; if(isUserInRole(appName, mappedRole) ) { if( debug>0 ) log("Role match " + roles[i] + " " + mappedRole); return OK; } if( debug>0 ) log("Role match failed " + roles[i] + " " + mappedRole); } if( debug>0 ) log("UnAuthorized " + role + " " + mappedRole); return DECLINED; // XXX check transport } // -------------------- Security -------------------- /* J2EE stores the security information in per/thread data ( SecurityContext). The web server will respect web.xml - including constraints, roles, auth methods. In order to access the J2EE realm it will use those methods. XXX This is based on how the current code works. It may be a good idea to make authenticate return the Principal or null, drop getUserPrincipal, and pass the Principal to isUserInRole. ( this avoids per/thread data - and it's more generic ) */ private LoginContext initLoginContext(String realm) { for(int i=0; i < MAX_COUNT; ++i) { try { if (debug>0) log("Getting auth for:" + i); LoginContext lc= new LoginContext(); lc.setRealmName(realm); return lc; } catch(Exception e) { e.printStackTrace(Log.err); try { Thread.sleep(SLEEP_TIME); }catch(InterruptedException ie) { } } } return null; } /** Return the current user, as set by authenticate() */ public Principal getUserPrincipal() { SecurityContext sc=SecurityContext.getCurrent(); if( sc==null ) return null; return sc.getCallerPrincipal(); } /** Check if the current user has the specified role. * The user is set in the thread data. * * It will be called with the role specified in web.xml/role-ref */ public boolean isUserInRole(String appName, String rname) { RoleMapper rmap = RoleMapper.getRoleMapper( appName ); if(debug>0) log("Mapping role " + rname + " " + rmap); if(rmap != null) { for(Enumeration e = rmap.getCurrentRoles(); e.hasMoreElements();) { Role r = (Role) e.nextElement(); if( debug>0) log("Try " + r.getName()); if(r.getName().equals(rname)) return true; } } return false; } // -------------------- Logging implementation -------------------- /* Very inefficient - we do a hashtable lookup per context. We could use context notes to speed up if needed. */ private synchronized void intLogRequest(String ctxPath, String uri, String respString ) { Log accessLog = getAccessLog(ctxPath); accessLog.println(localStrings. getLocalString( "web.security.request.on.at", "Request for {0} on {1} at {2} ", new Object[] {uri, ctxPath, new Date() + "." + respString })); accessLog.flush(); } private synchronized void intLogError(String ctxPath, String uri, String respString) { Log errorLog = getErrorLog(ctxPath); errorLog.println("Error serving Request " + uri + " on " + ctxPath + " at " + new Date() + ". " + respString); errorLog.flush(); } private synchronized Log getLog(String contextName, String propName, String defaultValue) { try { File dir = LogUtil.getLogDirectory(contextName, LogUtil.WEB_LOG); String fname = config.getProperty(propName, defaultValue); File logFile = new File(dir, fname); if(!logFile.exists()) { logFile.createNewFile(); } FileLogWriter fwriter = new FileLogWriter(logFile, BUFFER_SIZE); return Log.getLog(fwriter); } catch(Exception e) { e.printStackTrace(); Log.err.println(e); return Log.err; } } private Log getAccessLog(String contextName) { Log aLog = (Log) accessLogs.get(contextName); if(aLog == null) { aLog = getLog(contextName, HTTP_ACCESS_LOG, "access.log"); accessLogs.put(contextName, aLog); } return aLog; } private Log getErrorLog(String contextName) { Log aLog = (Log) errorLogs.get(contextName); if(aLog == null) { aLog = getLog(contextName, HTTP_ERROR_LOG, "error.log"); errorLogs.put(contextName, aLog); } return aLog; } } |
... this post is sponsored by my books ... | |
![]() #1 New Release! |
![]() FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.