getCallerPrincipal fundamentally broken when not behind secu
bstratford Apr 12, 2002 3:57 PMProblem:
I'm finding that getCallerPrincipal returns a random result
when accessed through a servlet using an unprotected
(by security-constraint) servlet-mapping.
I'm using JBoss 2.4.4 and Tomcat 4.0.1 bundle. The behavior didn't
change when I switched to Tomcat 4.0.3 (copied in on top of 4.0.1).
This behavior is insensitive to the LoginManager -- it's
repeatable using both UsersRolesLoginModule and DatabaseServerLoginModule.
I'm using FORM based authentication -- not sure if this matters.
Test Setup:
I have a servlet that can be accessed either through /auth or /noauth
servlet-mapping. /auth requires authentication into the User role.
The servlet accesses a stateless session bean and calls a single method
ssb.getCallerPrincipal(). This method does context.getCallerPrincipal,
prints out the result, and returns.
Scenarios:
1. Dangerous
- open new browser
- hit /noauth; getCallerPrincipal = nobody
- hit /auth; authenticate as "joebob"; getCallerPrincipal = joebob
- hit /noauth; hit reload 20 times quickly; getCallerPrincipal sometimes returns 'nobody', sometimes 'joebob'
2. VERY Dangerous
- open new browser B1 [ e.g. Mozilla ]
- hit /auth; authenticate as "joebob"; getCallerPrincipal = joebob
- hit /auth; hit reload 20 times quickly; getCallerPrincipal always returns 'joebob'
- open a totally new browser B2 [ e.g. Netscape ]
- hit /noauth; hit reload 20 times quickly; getCallerPrincipal sometimes returns 'nobody', sometimes 'joebob'
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Servlet:
public class EJBConnectServlet extends PMBaseServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, java.io.IOException {
try {
CTestFacadeHome home = (CTestFacadeHome) AppManager.getAppManager().getEJBManager().getEJBHome("CTestFacade");
CTestFacade tf = home.create();
tf.getCallerPrincipal();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SessionBean
public class CTestFacadeBean implements javax.ejb.SessionBean, CTestFacadeInterface {
private transient SessionContext context = null;
private Context getNamingContext() throws NamingException {
Properties props = new Properties();
props.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.provider.url", "localhost:8099");;
return new InitialContext(props);
}
public void ejbActivate() throws javax.ejb.EJBException, java.rmi.RemoteException {
}
public void ejbPassivate() throws javax.ejb.EJBException, java.rmi.RemoteException {
}
public void ejbRemove() throws javax.ejb.EJBException, java.rmi.RemoteException {
}
public void setSessionContext(javax.ejb.SessionContext sessionContext) throws javax.ejb.EJBException, java.rmi.RemoteException {
context = sessionContext;
}
public void ejbCreate() throws CreateException, RemoteException {
}
public void getCallerPrincipal() throws RemoteException {
try {
System.out.println("test-facade::getCallerPrincipal=" + context.getCallerPrincipal().toString());
Thread.sleep(1000);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
web.xml
<servlet-name>EJBConnectServlet</servlet-name>
<servlet-class>com.purematrix.zm.auth.servlet.EJBConnectServlet</servlet-class>
<servlet-mapping>
<servlet-name>EJBConnectServlet</servlet-name>
<url-pattern>/auth</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>EJBConnectServlet</servlet-name>
<url-pattern>/noauth</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name> Require Authorization </web-resource-name>
<url-pattern>/auth</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>User</role-name>
</auth-constraint>
</security-constraint>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ejb-jar.xml
<ejb-name>CTestFacade</ejb-name>
com.purematrix.zm.ejb.pmi_user.CTestFacadeHome
com.purematrix.zm.ejb.pmi_user.CTestFacade
<ejb-class>com.purematrix.zm.ejb.pmi_user.CTestFacadeBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<container-transaction>
<ejb-name>CTestFacade</ejb-name>
<method-name>*</method-name>
<trans-attribute>RequiresNew</trans-attribute>
</container-transaction>
<method-permission>
<role-name>User</role-name>
<ejb-name>CTestFacade</ejb-name>
<method-name>*</method-name>
</method-permission>
<method-permission>
<ejb-name>CTestFacade</ejb-name>
<method-name>create</method-name>
<ejb-name>CTestFacade</ejb-name>
<method-name>getCallerPrincipal</method-name>
</method-permission>