Announcement Announcement Module
Collapse
No announcement yet.
default constructor in User and GrantedAuthorityImpl Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • default constructor in User and GrantedAuthorityImpl

    Hi,
    I would like to know why the default constructors in User and GrantedAuthorityImpl throw IllegalArgumentException. This makes their use as base classes for my hibernatre persisted classes difficult.

  • #2
    They strictly enforce the arguments specifically because many end users write their own AuthenticationDao and often "strange" problems with Acegi Security are reported, only to be a violation of the AuthenticationDao interface contract. So it's an effort to help people write conforming AuthenticationDao implementations.

    In my own applications I usually have a Party that knows nothing about Acegi Security. I then write a subclass of User that looks something like this:

    Code:
    public class CustomUser extends User {
    
    	private Party party;
    	
    	public User(Party party, GrantedAuthority[] authorities, boolean accountNonLocked) {
    		super(party.getUsername(), party.getPassword(), true, true, true, accountNonLocked, authorities);
    		this.party = party;
    	}
    	
    	public Party getParty() {
    		return this.party;
    	}
    	
    	public String toString() {
            StringBuffer sb = new StringBuffer();
            sb.append(super.toString() + ": ");
            sb.append("Internal Party: " + this.party);
            return sb.toString();
    	}
    }
    As such my Party is available via the ContextHolder, and my AuthenticationDao has a pretty simply job of just retrieving my Party and passing it, along with an array of GrantedAuthority instances, to my CustomUser.

    Comment


    • #3
      Thanks for your reply.
      My plan was to use hibernate's realtions' mapping to manage the realtion between the user and its granted authorities. I think that the solution you described works well but what about GrantedAuthority[] getAuthorities() ?
      I would like to subclass GrantedAuthorityImpl to represent my roles (it's advised in the documentation to use GrantedAuthorityImpl) to manage it's relation with the User using hibernate. This is not straightforward now because of the exception thrown in the default constructor and beacuse of the lack of setRole in GrantedAuthorityImpl.
      I think I can manage that by calling super(null) in my default constructor and by setting hibernate's access to the property "role" as "field" but this is rather ugly and awkward.
      Can you see any easier method ?

      Comment


      • #4
        Perhaps a cut-down version of my AuthenticationDao that calls the CustomUser contructor I previously posted will shed some light:

        Code:
        public class AcegiAuthenticationDao implements AuthenticationDao, InitializingBean {
        
        	protected final Log logger = LogFactory.getLog(AcegiAuthenticationDao.class);
        	
        	private PartyManager partyManager;
        	private RoleMemberManager roleMemberManager;
        	
        	public UserDetails loadUserByUsername(String username)
        			throws UsernameNotFoundException, DataAccessException {
        		// Attempt lookup (NB: this services layer method does NOT require ContextHolder to be set)
        		Party party = partyManager.readUsername(username, subscriberId);
        		if (party == null) {
        			throw new UsernameNotFoundException("User not found; username='" + username + "'");
        		}
        		
        		// Check for locked user
        		UserDetails user;
        		if (party.getAttemptsRemaining().intValue() == 0) {
        			if (logger.isDebugEnabled()) {
        				logger.debug("User has no attempts remaining");
        			}
        			user = new CustomUser(party, getAuthorities(party), false);
        		} else {
        			user = new CustomUser(party, getAuthorities(party), true);
        		}
        		
        		if (logger.isDebugEnabled()) {
        			logger.debug("Returning user: " + user.toString());
        		}
        		return user;
        	}
        
        
        	private GrantedAuthority[] getAuthorities(Party party) {
        		List results = roleMemberManager.findAllRoles(party);
        		if (results.size() == 0) {
        			throw new UsernameNotFoundException("User found, but contains no role memberships");
        		}
        		
        		List authorities = new Vector();
        		Iterator iter = results.iterator();
        		while (iter.hasNext()) {
        			RoleMember member = (RoleMember) iter.next();
        			authorities.add(new GrantedAuthorityImpl("ROLE_" + member.getRole().getRole()));
        		}
        		
        		// add a generic role to indicate an authenticated user
        		authorities.add(new GrantedAuthorityImpl("ROLE_AUTHENTICATED_PRINCIPAL"));
        		
        		return (GrantedAuthority[]) authorities.toArray(new GrantedAuthority[] {});
        	}
        	
        	
        	public void afterPropertiesSet() throws Exception {
        		Assert.notNull(partyManager);
        		Assert.notNull(roleMemberManager);
        	}
        	
        	public PartyManager getPartyManager() {
        		return partyManager;
        	}
        	public void setPartyManager(PartyManager partyManager) {
        		this.partyManager = partyManager;
        	}
        	public RoleMemberManager getRoleMemberManager() {
        		return roleMemberManager;
        	}
        	public void setRoleMemberManager(RoleMemberManager roleMemberManager) {
        		this.roleMemberManager = roleMemberManager;
        	}
        Basically, my domain objects have no awareness at all of Acegi Security. The job of AuthenticationDao and CustomUser is to turn my rich (security unaware) domain objects into something Acegi Security can work with. Just use standard OO modelling and keep Acegi Security-specific abstractions out of your domain model.

        Comment

        Working...
        X