Folks,

Here is my use model for users.

Login attempt
if user exists, then login them in (works fine)elseuser does not existinside 
doGetAuthenticationInfo I create the user and return
Case #2 never makes it to doGetAurthorization method my login returns with "no 
account for this user exists within shiro". But by this time the attempted 
login created a user in the database.

On the second login attempt... all goes well and the user is logged in.

Can someone tell me whats going on here ?
Did I miss doing somethign within doGetAuthenticationInfo to let shiro know 
that a user is now authenticated ?

Thanks for any help

Here is my realm...

package org.tynamo.examples.pphl.services.realms;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SaltedAuthenticationInfo;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.authz.permission.WildcardPermissionResolver;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.crypto.hash.Sha1Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.SimpleByteSource;
import org.apache.tapestry5.alerts.AlertManager;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.services.ApplicationStateManager;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.tynamo.builder.BuilderDirector;
import 
org.tynamo.common.services.authenticationlisteners.SecurityAuthenticationToken;
import org.tynamo.examples.pphl.AdminLayoutBuilder;
import org.tynamo.examples.pphl.HitCounterBuilder;
import org.tynamo.examples.pphl.PersonBuilder;
import org.tynamo.examples.pphl.model.AdminLayout;
import org.tynamo.examples.pphl.model.HitCounter;
import org.tynamo.examples.pphl.model.Person;
import org.tynamo.examples.pphl.model.Person.Permission;
import org.tynamo.examples.pphl.model.Person.Role;
import org.tynamo.security.federatedaccounts.services.FederatedAccountService;
import org.tynamo.services.DescriptorService;
import org.tynamo.services.PersistenceService;
import org.tynamo.util.Utils;

/**
 * Refer to RollingTokenRealm to finish proper federate logic
 * 
 * @author Owner
 * 
 */
public class HibernateUserRealm extends AuthorizingRealm
{
    public static final String HIBERNATEUSER_CLIENTID_USERNAME = 
"hibernateuser.clientid";

    public static final String HIBERNATEUSER_CLIENTSECRET_PASSWORD = 
"hibernateuser.clientsecret";

    public static final String HIBERNATEUSER_PERMISSIONS = 
"hibernateuser.permissions";

    public static final String HIBERNATEUSER_PRINCIPAL = 
"hibernateuser.principal";

    /**
     * All we need to get into facebook and drill down is the login
     * email/password and id for reference
     */
    public static enum PrincipalProperty
    {
        id, email, name
    };

    private PrincipalProperty principalProperty;

    private final Logger logger;

    private FederatedAccountService federatedAccountService;

    private Session session;

    private String clientIdUserName;

    private String clientSecretPassword;

    private String permissions;

    public HibernateUserRealm(Logger logger, FederatedAccountService 
federatedAccountService, Session session,
            @Inject @Symbol(HibernateUserRealm.HIBERNATEUSER_CLIENTID_USERNAME) 
String clientIdUserName,
            @Inject 
@Symbol(HibernateUserRealm.HIBERNATEUSER_CLIENTSECRET_PASSWORD) String 
clientSecretPassword,
            @Inject @Symbol(HibernateUserRealm.HIBERNATEUSER_PERMISSIONS) 
String permissions,
            @Inject @Symbol(HibernateUserRealm.HIBERNATEUSER_PRINCIPAL) String 
principalPropertyName)
    {
        super(new MemoryConstrainedCacheManager()); // caches your user account
                                                    // on next iterations thru
        this.logger = logger;
        this.federatedAccountService = federatedAccountService;
        this.session = session;

        // Let this throw IllegalArgumentException if value is not supported
        this.clientIdUserName = clientIdUserName;
        this.clientSecretPassword = clientSecretPassword;
        this.permissions = permissions;
        this.principalProperty = 
PrincipalProperty.valueOf(principalPropertyName);

        setName(HibernateUserRealm.class.getSimpleName());

        // setAuthenticationTokenClass(FacebookAccessToken.class);
        //setAuthenticationTokenClass(UsernamePasswordToken.class);
        
        // !!!!!!! LISTENER SETUP HERE !!!!!!!
        setAuthenticationTokenClass(SecurityAuthenticationToken.class);
        
        setPermissionResolver(new WildcardPermissionResolver());

        //setCredentialsMatcher(new 
HashedCredentialsMatcher(Sha1Hash.ALGORITHM_NAME));
    }
    
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection 
principals)
    {
        if (principals == null)
            throw new AuthorizationException("PrincipalCollection was null, 
which should not happen");

        if (principals.isEmpty())
        {
            System.out.println("principals collection is empty");
            return null;
        }
        
        if (principals.fromRealm(getName()).size() <= 0)
        {
            System.out.println("principals from realm collection is empty");
            return null;
        }

        //String username = (String) 
principals.fromRealm(getName()).iterator().next();
        //String username = (String) 
principals.fromRealm(getName()).iterator().next();
        //if (username == null)
        //    return null;
        //Person person = findByUsername(username);
        //if (person == null)
        //    return null;
        
        Person user = applicationStateManager.get(Person.class);
        // do roles
        
        Set<String> rroles = new HashSet<String>(user.getRoles().size());
        Set<Role> roles = user.getRoles();
        for (Role role : roles)
            rroles.add(role.name());        
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(rroles);
        
        // do permissions
        // this is enum - Set<String> permissions = new HashSet<String>();
        Set<Permission> permissions = user.getPermissions();
        for (Permission permission : permissions) 
            if (!principals.fromRealm(getName()).isEmpty()) 
info.addStringPermission(permission.name());
        
        
        //SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        /*



        Set<String> shiroPermissions = new HashSet<String>();
        for (Person.Permission permission : Person.Permission.values()) 
        {
            shiroPermissions.add(permission.toString());
        }
        info.setStringPermissions(shiroPermissions);

        Set<org.apache.shiro.authz.Permission> userPermissions = new 
HashSet<org.apache.shiro.authz.Permission>();
        for (Person.Permission permission : Person.Permission.values()) 
        {
            
info.addObjectPermission(getPermissionResolver().resolvePermission(permission.name()));
            // org.apache.shiro.authz.Permission p =
            // getPermissionResolver().resolvePermission(permission.name());
            // userPermissions.add(p);
        }
        // info.setObjectPermissions(userPermissions);
*/
        return info;
    }

    private Person findByUsername(String username)
    {
        return (Person) 
session.createCriteria(Person.class).add(Restrictions.eq("username", 
username)).uniqueResult();
    }

    private Set<String> findRolesByUsername(Person person)
    {
        Set<String> result = new HashSet<String>();

        Iterator<Role> iterator = person.getRoles().iterator();
        while (iterator.hasNext())
        {
            Role role = iterator.next();
            result.add(role.toString());
        }

        return result;
    }

    private Set<String> findPermissionsByUsername(Person person)
    {
        Set<Permission> permissions = new HashSet<Permission>();

        Criteria criteria = session.createCriteria(Person.Permission.class);
        criteria.add(Restrictions.eq("Person_id", person.getId()));
        permissions.addAll(criteria.list());

        Set<String> result = new HashSet<String>();

        Iterator<Permission> iterator = permissions.iterator();
        while (iterator.hasNext())
        {
            Permission permission = iterator.next();
            result.add(permission.toString());
        }

        return result;
    }

    @Inject
    private DescriptorService descriptorService;

    @Inject
    private BuilderDirector builderDirector;

    @Inject
    private PersistenceService persistenceService;

    private PersonBuilder pb = new PersonBuilder();

    private AdminLayoutBuilder ab = new AdminLayoutBuilder();

    private HitCounterBuilder hcb = new HitCounterBuilder();

    @Inject
    private Messages messages;

    @Inject
    private AlertManager alertManager;

    @Inject
    private ApplicationStateManager applicationStateManager;

    Person createPerson(String username, String password)
    {

        // Person bean = builderDirector.createNewInstance(Coach.class);
        Person bean = pb.build();
        bean.setUsername(username);
        bean.setEmailAddress(username);
        bean.setPassword(password);
        bean.setFirstName(username.substring(username.indexOf('@') + 1));
        bean.setLastName(username.substring(username.indexOf('@') + 1));

        try
        {
            Transaction tx = session.beginTransaction();
            persistenceService.save(bean);
            
alertManager.info(messages.getFormatter(Utils.ADDED_MESSAGE).format(bean));
            tx.commit();

            // session.flush();

            // Transaction tx = session.beginTransaction();
            // persistenceService.save(bean);
            // session.save(bean);
            // 
alertManager.info(messages.getFormatter(Utils.ADDED_MESSAGE).format(bean));
            return bean;
        } catch (RuntimeException e)
        {
            // java.lang.RuntimeException: Exception constructing service
            // 'DescriptorService': Error invoking constructor public
            // 
org.tynamo.services.DescriptorServiceImpl(java.util.Collection,org.tynamo.descriptor.factories.DescriptorFactory):
            // java.lang.NullPointerException

            alertManager.info(e.toString());
        }

        return null;
    }

    AdminLayout createAdminLayout()
    {

        // Person bean = builderDirector.createNewInstance(Coach.class);
        AdminLayout bean = ab.build();

        try
        {
            Transaction tx = session.beginTransaction();
            persistenceService.save(bean);
            
alertManager.info(messages.getFormatter(Utils.ADDED_MESSAGE).format(bean));
            tx.commit();

            // session.flush();

            // Transaction tx = session.beginTransaction();
            // persistenceService.save(bean);
            // session.save(bean);
            // 
alertManager.info(messages.getFormatter(Utils.ADDED_MESSAGE).format(bean));
            return bean;
        } catch (RuntimeException e)
        {
            // java.lang.RuntimeException: Exception constructing service
            // 'DescriptorService': Error invoking constructor public
            // 
org.tynamo.services.DescriptorServiceImpl(java.util.Collection,org.tynamo.descriptor.factories.DescriptorFactory):
            // java.lang.NullPointerException

            alertManager.info(e.toString());
        }

        return null;
    }

    HitCounter createHitCounter()
    {

        // Person bean = builderDirector.createNewInstance(Coach.class);
        HitCounter bean = hcb.build();

        try
        {
            Transaction tx = session.beginTransaction();
            bean.setLoginPageHits(new Integer(0));
            persistenceService.save(bean);
            
alertManager.info(messages.getFormatter(Utils.ADDED_MESSAGE).format(bean));
            tx.commit();
            return bean;
        } catch (RuntimeException e)
        {
            alertManager.info(e.toString());
        }

        return bean;
    }

    @Override
    protected SaltedAuthenticationInfo 
doGetAuthenticationInfo(AuthenticationToken token) 
            throws AuthenticationException
    {
        SecurityAuthenticationToken upToken = (SecurityAuthenticationToken) 
token;
        //UsernamePasswordToken upToken = (UsernamePasswordToken) token;

        String username = new String((String) upToken.getPrincipal()); // 
typically
                                                                       // a
                                                                       // 
username
                                                                       // for a
                                                                       // upt
        String password = new String((String) upToken.getCredentials()); // 
typically
        //String password = new String(upToken.getPassword()); // typically
                                                                         // 
password
                                                                         // for
                                                                         // a
                                                                         // upt
        boolean rememberMe = upToken.isRememberMe();

        // Null username is invalid
        if (username == null)
        {
            throw new AccountException("Null usernames are not allowed by this 
realm.");
        }

        if (password.toString().length() < 1)
        {
            throw new IncorrectCredentialsException("Password cannot be null.");
        }

        // Person person = findByUsername(username);
        Criteria criteria = session.createCriteria(Person.class);
        criteria.add(Restrictions.ilike("username", username));
        Person person = (Person) criteria.uniqueResult();

        HitCounter hc = findHitCounter();
        if (person == null)
        {
            person = createPerson(username, password);
            
            hc.setCreatedUsers( hc.getCreatedUsers() + 1 );
        }
        hc.setLoginPageHits( hc.getLoginPageHits() + 1 );
        applicationStateManager.set(HitCounter.class, updateHitCounter(hc));

        synchronized (applicationStateManager)
        {
            applicationStateManager.set(Person.class, person);
            if (findAdminLayout() != null)
                applicationStateManager.set(AdminLayout.class, 
findAdminLayout());
            else
            {
                createAdminLayout();
                applicationStateManager.set(AdminLayout.class, 
findAdminLayout());
            }
        }
        SimpleByteSource bs = new 
SimpleByteSource(Base64.decode(person.getPasswordSalt()));

        return new SimpleAuthenticationInfo(username, token.getCredentials(), 
bs, getName());
    }

    private HitCounter updateHitCounter(HitCounter bean)
    {
        try
        {
            Transaction tx = session.beginTransaction();
            persistenceService.save(bean);
            
alertManager.info(messages.getFormatter(Utils.SAVED_MESSAGE).format(bean));
            tx.commit();
        } catch (RuntimeException e)
        {
            alertManager.info(e.toString());
        }
        return bean;
    }

    /**
     * Find Methods
     * 
     * @return
     */
    private AdminLayout findAdminLayout()
    {
        return (AdminLayout) 
session.createCriteria(AdminLayout.class).add(Restrictions.eq("id", 
1)).uniqueResult();
    }

    private HitCounter findHitCounter()
    {
        HitCounter bean = (HitCounter) 
session.createCriteria(HitCounter.class).add(Restrictions.eq("id", 
1)).uniqueResult();

        if (bean == null)
            bean = createHitCounter();
        
        return bean;
    }
}

                                          

Reply via email to