3

This is not a simple question its just because i'm rethinking our architecture for securing our EJB 3.0 service by a login and security.

We have a EJB3.0 application on JBoss 5.1 that offers various services to a SWT client to read and write data. To use a service, the client must login with a valid user and password which is looked up by SpringSecurity in a LDAP server. SpringSecurity generates a session id which is passed back to the client to be resused in any further service call.

client                            server
   |                                |
   |-> login(user/password)-------->|
   |                                |
   | <------- sessionId ------------| 
   |                                |
   |-->serviceXy(sessionId,param1)->|

The situation seems clear. We store the sessionId in our own context object which is the first parameter of each service method. There is an interceptor on each service method which reads the sessionId from the given context object and checks if the session is still valid. The client needs to call the login service first to get a context object filled with the sessionId and reusue this context object in further service calls.

public class OurContext {
    private String sessionId;
}


@Stateless
@Interceptors(SecurityInterceptor.class)
public OurServiceImpl implements OurService {

    public void doSomething(OurContext context, String param1) {
        [...]
    }
}

The thing i don't like at this solution is the polution of each service method with the context parameter. Isn't there a similar mechanism like a http session in rmi calls? I'm thinking of putting our context object in some kind of session that is created in the client(?) right after the login and is passed to the server on each service call so that the SecurityInterceptor can read the sessionId from this "magic context".

Something like this:

OurContext ctx = service.login("user","password");
Magical(Jboss)Session.put("securContext", ctx);
service.doSomething("just the string param");
martin
  • 980
  • 1
  • 13
  • 28

3 Answers3

2

Since you are already using an app server, it seems that you should be using the built-in EJB security mechanisms, generally provided through JAAS. On the 4.x jboss line, if you implemented your own JAAS plugin for jboss, you could get access to a "special" context map (similar to what you describe) which is passed along on remote requests (by the jboss remote invocation framework). I haven't used jboss in a while, so not sure how this maps to the 5.1 product, but i have to imagine it has similar facilities. This assumes, of course, that you are willing to implement something jboss specific.

jtahlborn
  • 52,909
  • 5
  • 76
  • 118
  • Well, after thinking a lot about your answer, i must admit, i can't find a better solution =). So we will keep our context scenario caused by political reasons, hrmpf – martin Jan 12 '12 at 09:07
1

There are some kinds of session mechanisms in EJB, but they all start when the remote call starts, and ends when that ends. On old one is the transaction context ( Adam Bien wrote about this some time ago), and a newer one the CDI Session Scope.

Contrary to popular belief, this scope doesn't just mirror the http session scope, but in absence of an http session (like for remote calls), it represents a single call chain or message delivery (for mdbs).

With such a session, your remote SWT client still has to pass the sessionId to the remote service, but any local beans called from there can pick it up from this "cdi" session.

The other option is kinda like what jtahlborn says: with your own login module you can return a custom principal, instead of the default one. Your code can first request the normal principal and then try to cast it.

The problem is that this stuff is container specific and JBoss always forgets about it. It pretty much breaks after every update, and users have to kick and scream to get it fixed in some next version (only to see it break again in the version after that). Without JBoss really supporting this it's an endless battle.

Yet another option is to let the user login with the sessionId as name. The login module behind that could be a simple module that accepts everything and just puts a principal in the security context with the sessionId as 'name'. It's a little weird, but we've used this succesfully to get any data that can be expressed by a string into the security context. Of course, you would need to let your client do a regular container authentication here, which kinda defeats using Spring security in the first place.

Mike Braun
  • 3,729
  • 17
  • 15
0

We went for another approach which is portable and does not rely on a specific app server. In addition our security implementation frees us from the restrictions of the EJB approach (which by the way I thought were closed 2 decades ago ... but came up again).

Looking top down:

There is a server providing classes with methods to work on same data. The client(s) provide the data and invoke specific methods.

Our approach is to put all data (and therefore communication between client and server) into a "Business Object". Every BO extends a superclass. This superclass contains a session id. The login method provides and returns that id. Every client only has to ensure to copy the id received in one BO into the next one it sends to the server. Every method which can be remotely (or locally) invoked, first obtains the session object with the received id. The method to return the session object also checks security constraints (which are based on permissions and not on roles like in the EKB approach).

Jemolah
  • 1,962
  • 3
  • 24
  • 41
  • 1
    Sounds quite well. How is your approach for service methods that does not have any paramters? – martin Feb 27 '12 at 08:09