It's weird that you login only one time.
Normally you should login on each request otherwise it is not working.
We already have this problem on our web service implementation
At each web service call we perform a login - without this it's not working.

Can you send me a simple example that can be used to reproduce this?

Bogdan

P.S.
It is recommended to use RepositoryManager to open a session and not directly
by calling

CoreInstance.getInstance().open(repository,null)

So the recommended way is to do:

RepositoryManager mgr = Framework.getService(RepositoryManager.class);
               Repository repo = mgr.getRepository(repositoryName);
               session = repo.open();

or if you have a single repopsitory

RepositoryManager mgr = Framework.getService(RepositoryManager.class);
               Repository repo = mgr.getDefaultRepository();
               session = repo.open();


Do not forget to close your session when you are no more using it by calling

CoreInstance.getInstance().close(session);


In future the close method will be available on the repository itself.
For now you need to use

CoreInstance.getInstance()

to close it but in future the CoreInstance class will be removbed from the API and will be an implementation detail.

Bogdan


Filipchik Alexander wrote:
Thank. I'll try to implement this approach in my app.

But: why does my current approach work?
Now I execute Framework.login() one time, when my web-application (tomcat)
starts. Then, when requests are coming on server-side I simple execute -
CoreInstance.getInstance().open(repository,null);

Every request is executed in own thread. But it not causes security errors.
Why? (Framework.logout I call when web-app is shutting down)

Alexander.

-----Original Message-----
From: Bogdan Stefanescu [mailto:[EMAIL PROTECTED] Sent: Tuesday, August 07, 2007 1:39 PM
To: Filipchik Alexander
Cc: 'Nuxeo List'
Subject: Re: [Ecm] Nuxeo security system and Remoting

Filipchik Alexander wrote:
Hello friends.
Now I am investigating your security approach connected to Nuxeo-Remote
framework. I found, that interaction with remote Nuxeo server starts with calling an Framework.login(username, userpassword).
What is confusing me - it's an static methods.
After I had login in  I can create sessions by
CoreInstance.getInstance().open(repository, null).
It's another static method.
Yes they are static - but there is nothing wrong with that.
They act as a facade to simplify API - but inside they call non static methods.
For example
Framework.login(username, password);
is a shortcut for

Framework.getRuntime().getService(LoginService.class).login(username, password);
or .. this is the same as
Framework.getLocalService(LoginService.class).login(username, password);

and LoginService.login(...) is not static.

This method is finally calling

        LoginContext ctx = new LoginContext(name, handler);
        ctx.login();

which is part of java.security API.

There is nothing wrong with being static or not.

Its means that I can't create sessions for several users in one time.
You can but in a thread you can have only one login context at a time.
So if you want to use several logins you need to logout first and then re-login using a different account
Or you may also use different threads each one using its own login context.

The problem is that after you logout you need to refetch a new CoreSession (because the core session you already have was created in the old login context and you need the new core session to be validated in the new context)

We already have this working in Apogee (Apogee is a nuxeo ECM rich client based on Eclipse RCP) I am currently working on simplifying client environment and connection configuration. You can take a look at this project to see examples or to reuse some modules.


I will explain here how the login is done on the client side to make things clear for everyone:

To login through a javax.security.auth.LoginContext you need to call:

LoginContext lc = Framework.login(username, password);

This will use lookup right LoginModule to login on Nuxeo ECM server and will use that module
to perform the login, then it returns the login context:

The login is done as follow:

    public LoginContext login(String username, Object credentials)
            throws LoginException {
DefaultCallbackHandler handler = new DefaultCallbackHandler(username,
                credentials);
        LoginContext ctx = new LoginContext(name, handler);
        ctx.login();
        return ctx;
    }

Later you can logout using the renturned context:
lc.logout();

Now, what exactly happens after the login method is called?

        LoginContext ctx = new LoginContext(name, handler);
        ctx.login();

This is explained in LoginContext javadoc.

The login configuration will be queried about the login module registered for the specified security domain (the name argument) and then the registered login module will be used to perform the login using the passed credentials.

In our case the security domain name is "nuxeo-client-login" and the login module registered for this domain
is
org.jboss.security.ClientLoginModule

So finally the Framework.login(username, password) method will end up in calling the methods

org.jboss.security.ClientLoginModule.login()
and then
org.jboss.security.ClientLoginModule.commit()

This is performing the login specific to a JBoss client

If you look into the code in org.jboss.security.ClientLoginModule you will se that jboss is doing the login as follows:

   public static void pushSubjectContext(Subject subject,
      Principal principal, Object credential)
   {
      SecurityManager sm = System.getSecurityManager();
      if (sm != null)
         sm.checkPermission(setPrincipalInfoPermission);

      // Set the legacy single-value access points
      if (server)
      {
         threadPrincipal.set(principal);
         threadCredential.set(credential);
      }
      else
      {
         SecurityAssociation.principal = principal;
         SecurityAssociation.credential = credential;
      }
      // Push the subject context
SubjectContext sc = new SubjectContext(subject, principal, credential);
      threadSubjectStacks.push(sc);
      if (trace)
         log.trace("pushSubjectContext, subject=" + subject + ", sc="+sc);
   }

where threadPrincipal and threadCredential are thread local variable.


What means all this?

It means that in fact when you perform a Framework.login(username, password)
the login context (username and credentials) are pushed in a thread local stack attached to the current thread and the first time you will access a protected bean remotely JBoss will use the information available in this stack
(by doing a stack.peek).
So the real login (authentication) on the server side is made when you first access a protected bean and not when you call the login method.

This also means that the login is valid only in the current thread - so if you are using mutliple threads you need to do for each one a new login. This also means that you can perform several login in a thread to switch the identity and the restore the old login using a logout (which will pop the current login from the local thread stack).
LoginContext lc1 = Framework.login("u1", "p1");
//... do something
LoginContext lc2 = Framework.login("u2", "p2");
// .. do domething
lc2.logout();
// now we are back in the lc1 context
lc1.logout();
// now we are no more logged in

Note that I have *not* tested this but theoretically it should work.

This also means the login itself is not costly -> it initialize only a thread local variable and the authentication on the server side is done later when you access a protected bean.

I hope this will clarify how login works.
If you have more question do not hesitate

Regards,
Bogdan



In my test integration application I create next approach:

1) When my web-app is starting - I init Nuxeo-Remoting (Framework,..) and
do
login as Administrator.
2) I add and delete documents
3) When I shoot down application - I do logout.
But in this way - I interact with Nuxeo only under Administrator user.


How will I have to change it, to allow permission management on Nuxeo
side?
For example:
1) I add login page into my application
2) When app is starting - I init Nuxeo-remote
3) When I need to add or delete document - I do Framework.login (using
current user credentials), getSession, logout (all in synchronize
section).
Is it right way? If yes - is it good for performance? Can I create an holder, that can holds session factory each loggined user
to
avoid login/logout actions on each remote call and multi threading
killing?
Alexander

_______________________________________________
ECM mailing list
[email protected]



_______________________________________________
ECM mailing list
[email protected]
http://lists.nuxeo.com/mailman/listinfo/ecm

Reply via email to