Ok, take a sample (I have removed inessential code).

1) Contains Nuxeo context:

public class NuxeoContextImpl implements NuxeoContext, InitializingBean {
    // logger
    private static final Log _log =
LogFactory.getLog(NuxeoContextImpl.class);

    private List<String> configurations;
    private String streamingServiceConfiguration;

    protected static RuntimeService runtime;
    protected final File home;
    protected Boolean initiated = new Boolean(false);
    private String repository;
    protected String username;
    protected String password;
    protected String domain;



    public NuxeoContext (String homeFileName) {
        this.home = new File(homeFileName);
    }

    public List<String> getConfigurations() {
        return configurations;
    }

    public void setConfigurations(List<String> configurations) {
        this.configurations = configurations;
    }

    public void init() throws Exception {
        synchronized (initiated) {
            if (!initiated) {
                runtime = new SimpleRuntime(home);
                Framework.initialize(runtime);
                deployConfiguration();
                initiated = true;
            }
        }
    }

    public void shutdown() throws Exception {
        synchronized (initiated) {
            if (initiated) {
                Framework.shutdown();
            }
        }
    }

    private void deployConfiguration() {
        for (String config : configurations) {
            deploy(config);
        }
        if (streamingServiceConfiguration != null) {
            deploy(streamingServiceConfiguration);
        }
    }

    protected void deploy(String bundle) {
        URL url = getResource(bundle);
        assert url != null;
        try {
            Framework.getRuntime().getContext().deploy(url);
        } catch (Exception e) {
            _log.error(e, e);
        }
    }

    protected URL getResource(String resource) {
        return runtime.getContext().getResource(resource);
    }

    protected void loginSystem() throws LoginException {
        Framework.login();
    }

    protected void login(String username, String userpassword) throws
LoginException {
        Framework.login(username, userpassword);
    }

    public CoreSession getCoreSession() throws ClientException {
        return CoreInstance.getInstance().open(repository, null);
    }

    public void closeSession(CoreSession session) throws ClientException {
        CoreInstance.getInstance().close(session);
    }


    public void afterPropertiesSet() throws Exception {
        init();
        if (username != null && password != null) {
            login(username, password);
        } else {
            loginSystem();
        }
        createDefaultStructure();
    }
}

2) Helps to execute Nuxeo calls like hibernate calls :) :
public interface NuxeoCallback {
    Object doInNuxeo(CoreSession session) throws ClientException,
DataAccessException;
}

public abstract class NuxeoDAOTemplate {

    // logger
    private static final Log _log =
LogFactory.getLog(NuxeoDAOTemplate.class);

    //protected CoreSession session;
    protected NuxeoContext nuxeo;
   

    public NuxeoContext getNuxeo() {
        return nuxeo;
    }

    public void setNuxeo(NuxeoContext nuxeo) {
        this.nuxeo = nuxeo;
    }

    /**
     * Creates new session
     *
     * @return
     * @throws ClientException
     */
    protected CoreSession getSession() throws ClientException {
        return nuxeo.getCoreSession();
    }

    /**
     * Closes session
     *
     * @param session
     * @throws ClientException
     */
    protected void closeSession(CoreSession session) throws ClientException
{
        nuxeo.closeSession(session);
    }

    /**
     * Commits changes
     *
     * @param session
     * @throws ClientException
     */
    protected void commit(CoreSession session) throws ClientException {
        if (session != null) {
            session.save();
        }
    }

    /**
     * Rollback changes
     *
     * @param session
     * @throws ClientException
     */
    protected void rollback(CoreSession session) throws ClientException {
        if (session != null) {
            session.cancel();
        }
    }

    /**
     * Gets search service
     *
     * @return
     */
    protected SearchService getSearchService() {
        return nuxeo.getSearchService();
    }


    /**
     * Executes NuxeoCallback
     *
     * @param action
     * @return
     * @throws DataAccessException
     */
    public Object execute(NuxeoCallback action) throws DataAccessException {
        CoreSession session = null;
        try {
            session = getSession();
            Object result = action.doInNuxeo(session);
            session.save();
            return result;
        } catch (ClientException e) {
            try {
                session.cancel();
            } catch (ClientException e1) {
                _log.error(e1, e1);
            }
            throw new DataAccessException(e);
        } finally {
            try {
                closeSession(session);
            } catch (ClientException e) {
                _log.error(e, e);
            }
        }
    }
}

3) Using it:

public DocumentModel getDocument(final String id) {
        DocumentModel doc = null;
        if (id != null && !id.trim().equals("")) {
            try {
                doc = (DocumentModel) execute(new NuxeoCallback() {
                    public Object doInNuxeo(CoreSession session) throws
ClientException, DataAccessException {
                        return session.getDocument(id);
                    }
                });
            } catch (DataAccessException e) {
                _log.error(e, e);
            }
        }
        return doc;
    }


As you see every call of execute(new NuxeoCallback()) creates a new session.
It helps to simplify iteraction with Nuxeo. It would be great if I will able
to put into a server-side session current user credentials. Another
question, how I put it into my DAO :)
-----Original Message-----
From: Bogdan Stefanescu [mailto:[EMAIL PROTECTED] 
Sent: Tuesday, August 07, 2007 2:24 PM
To: Filipchik Alexander
Cc: 'Nuxeo List'
Subject: Re: [Ecm] Nuxeo security system and Remoting


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