I have a use case where my own site (A) consolidates data from other sites. 
When a user logs into site A, those credentials are used to login to the
other sites.  A user might have access to all or none of the other sites.  

I launch threads to login to the other sites.  When I wait on all the
threads to complete, everything works as expected.  To speed up the login, I
want the login to return when the first successful login completes. 
However, when I do this, there seems to be a race condition where not all of
the successful principals are added.  Sometimes I get access to all the
sites, sometimes only a partial list.

*The real question is can principals be added to the AuthenticationInfo
object after it is returned from doGetAuthenticationInfo()?*

This is my doGetAuthenticationInfo code in my realm:

        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(
                        AuthenticationToken token) throws 
AuthenticationException {
                
                List<String> urls = getUrls();
                UsernamePasswordToken usernamePasswordToken =
(UsernamePasswordToken)token;
                MyAuthenticationInfo authInfo = new
MyAuthenticationInfo(token.getCredentials(),
                                                                                
                                                        this.getName());
                
                ArrayList<LoginTask> threads = new ArrayList<LoginTask>();
                for (String url: urls) {
                        LoginTask t = new LoginTask(url, usernamePasswordToken, 
authInfo);
                        t.start();
                        threads.add(t);
                }

                boolean successful = false;
                int threadsComplete = 0;
                while (!successful && threadsComplete < threads.size() - 1) {
                        threadsComplete = 0;
                        for (LoginTask t : threads) {
                                if (!t.isAlive()) {
                                        threadsComplete++;
                                        if (t.getPrincipal() != null) {
                                                successful = true;
                                                break;
                                        }
                                }
                                try {
                                        Thread.sleep(100);
                                } catch (InterruptedException e) {
                                }
                        }
                }
    
                return authInfo;
        }

The login thread calls this:

        public void run() {
                try {
                        String username = m_usernamePasswordToken.getUsername();
                        String password = new 
String(m_usernamePasswordToken.getPassword());
                        Subject s = SecurityUtils.getSubject();
                        String sessionId = s.getSession().getId().toString();
                        doLogin(m_url, username, password, sessionId);  
//throws exception if
login fails
                        
                        m_principal = new
MyPrincipal(m_usernamePasswordToken.getPrincipal().toString(), sessionId,
m_url.toLowerCase());
                        m_authInfo.addPrincipal(m_principal);
                } catch (Exception e) {
                } finally {
                        ThreadContext.unbindSubject();
                        ThreadContext.remove();
                }
        }

I'm guessing the problem is once the main thread in
doGetAuthenticationInfo() is returned, I can't add more principals to that
AuthenticationInfo object.  But why?  Is there a way around this?






--
View this message in context: 
http://shiro-user.582556.n2.nabble.com/Add-principals-to-AuthenticationInfo-object-after-doGetAuthenticationInfo-returns-tp7581395.html
Sent from the Shiro User mailing list archive at Nabble.com.

Reply via email to