Identifying a java.rmi.ServerException as a failed login exc
nlejeune Mar 18, 2005 6:10 AMHello Scott
First of all I'd like to congratulate you on your jaas_howto document, I found it very useful both in understanding the concepts as well as the implementation details of JBoss.
I will formulate my question around one of your example : example1-test2. That example tests access with an invalid password.
Here is an extract of the client code
try { AppCallbackHandler handler = new AppCallbackHandler(name, password); LoginContext lc = new LoginContext("TestClient", handler); System.out.println("Created LoginContext"); lc.login(); } catch (LoginException le) { System.out.println("Login failed"); le.printStackTrace(); } try { InitialContext iniContext = new InitialContext(); SessionHome home = (SessionHome) iniContext.lookup(example + "/PublicSession"); System.out.println("Found PublicSession home"); Session bean = home.create(); System.out.println("Created PublicSession"); System.out.println("Bean.echo('Hello') -> " + bean.echo("Hello")); bean.remove(); } catch (Exception e) { e.printStackTrace(); }
Even with a wrong password, the LoginException is never thrown. I understand this is due to the fact that the org.jboss.security.ClientLoginModule does not perform authentication. That behaviour is clearly stated in the documentation, I have no problem with that.
What troubles me is that the exception that will be received by the client when trying to create a bean is a java.rmi.ServerException, and that to identify it's actually a SecurityException I have to travel down the exception chain and cast the nested-nested exception to an EJBException.
Here is the exception that example1-test2 prints :
client-test2: [java] +++ Running SessionClient with username=java, password=badpass, example=example1 [java] Created LoginContext [java] Found PublicSession home [java] java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: [java] java.rmi.ServerException: EJBException:; nested exception is: [java] javax.ejb.EJBException: checkSecurityAssociation; CausedByException is: [java] Authentication exception, principal=java [java] at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:292) [java] at sun.rmi.transport.Transport$1.run(Transport.java:148) [java] at java.security.AccessController.doPrivileged(Native Method) [java] at sun.rmi.transport.Transport.serviceCall(Transport.java:144) [java] at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:460) [java] at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:701) [java] at java.lang.Thread.run(Thread.java:534) [java] at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:247) [java] at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:223) [java] at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:133) [java] at org.jboss.invocation.jrmp.server.JRMPInvoker_Stub.invoke(Unknown Source) [java] at org.jboss.invocation.jrmp.interfaces.JRMPInvokerProxy.invoke(JRMPInvokerProxy.java:135) [java] at org.jboss.invocation.InvokerInterceptor.invoke(InvokerInterceptor.java:96) [java] at org.jboss.proxy.TransactionInterceptor.invoke(TransactionInterceptor.java:46) [java] at org.jboss.proxy.SecurityInterceptor.invoke(SecurityInterceptor.java:53) [java] at org.jboss.proxy.ejb.HomeInterceptor.invoke(HomeInterceptor.java:173) [java] at org.jboss.proxy.ClientContainer.invoke(ClientContainer.java:85) [java] at $Proxy0.create(Unknown Source) [java] at org.jboss.docs.jaas.howto.SessionClient.main(SessionClient.java:79) [java] Caused by: java.rmi.ServerException: EJBException:; nested exception is: [java] javax.ejb.EJBException: checkSecurityAssociation; CausedByException is: [java] Authentication exception, principal=java [java] at org.jboss.ejb.plugins.LogInterceptor.handleException(LogInterceptor.java:347) [java] at org.jboss.ejb.plugins.LogInterceptor.invokeHome(LogInterceptor.java:124) [java] at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invokeHome(ProxyFactoryFinderInterceptor.java:93) [java] at org.jboss.ejb.StatelessSessionContainer.internalInvokeHome(StatelessSessionContainer.java:319) [java] at org.jboss.ejb.Container.invoke(Container.java:743) [java] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [java] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [java] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [java] at java.lang.reflect.Method.invoke(Method.java:324) [java] at org.jboss.mx.server.ReflectedDispatcher.dispatch(ReflectedDispatcher.java:60) [java] at org.jboss.mx.server.Invocation.dispatch(Invocation.java:61) [java] at org.jboss.mx.server.Invocation.dispatch(Invocation.java:53) [java] at org.jboss.mx.server.Invocation.invoke(Invocation.java:86) [java] at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:185) [java] at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:473) [java] at org.jboss.invocation.jrmp.server.JRMPInvoker.invoke(JRMPInvoker.java:360) [java] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [java] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [java] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [java] at java.lang.reflect.Method.invoke(Method.java:324) [java] at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:261) [java] at sun.rmi.transport.Transport$1.run(Transport.java:148) [java] at java.security.AccessController.doPrivileged(Native Method) [java] at sun.rmi.transport.Transport.serviceCall(Transport.java:144) [java] at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:460) [java] at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:701) [java] at java.lang.Thread.run(Thread.java:534) [java] Caused by: javax.ejb.EJBException: checkSecurityAssociation; CausedByException is: [java] Authentication exception, principal=java [java] at org.jboss.ejb.plugins.SecurityInterceptor.checkSecurityAssociation(SecurityInterceptor.java:166) [java] at org.jboss.ejb.plugins.SecurityInterceptor.invokeHome(SecurityInterceptor.java:83) [java] at org.jboss.ejb.plugins.LogInterceptor.invokeHome(LogInterceptor.java:120) [java] ... 25 more [java] Found PrivateSession home [java] Failed to create PrivateSession as expected
In my client code, to be sure the exception indicates a SecurityException and not another exception, I'd have to do something like
catch (RemoteException e) { Throwable cause = e.getCause(); if (cause != null) { cause = cause.getCause(); if (cause != null && cause instanceof EJBException) { cause = ((EJBException) cause).getCausedByException(); if (cause instanceof SecurityException) { // OK it was caused by a security problem, handle it ... } } } }
Is it the right way to do it or is there a more elegant approach? Or did I miss something about the authentication process?
Thank you for reading this
Nicolas Lejeune
Belgium.