Tag Archives: spring

Model variables for all views in Thymeleaf 2.1 with Spring MVC

Recently I’ve stumbled upon quite common problem – how to inject a few variables to every Thymeleaf view in application. Of course there is @ModelParam annotation, I could use interceptor or @ControllerAdvice. All solutions are described on StackOverFlow (it is about controllers).

The problem was that I wanted to put Maven build information in that model (to show version and build time in footer). Therefore I did not need application-scope wiring, as build informations are available during Spring’s container startup. So I’ve found another solution dealing with model itself on the lower level – pure XML configuration. There is a special property in ThymeleafViewResolver that can be used – static variables. So code sample can look like this:

<bean id="thymeleafViewResolver" class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
    <property name="templateEngine" ref="templateEngine" />
    <property name="characterEncoding" value="UTF-8" />
    <property name="staticVariables">
            <map>
                <entry key="myModelVariableIWantToSet" value="My model variable value" />
                <!-- All placeholders taken from context:property-placeholder tag can be used as value-->
            </map>
    </property>
</bean>

All defined variables are put into all Model instances that are linked to Thymeleaf views. If You are just serving plain JSON it does not go there – that can be expected behaviour or not! Be aware of that fact.

Advertisements

LDAP Authentication and DB authorisation with Grails Spring Security

Recently I faced quite simple problem – allow application to authenticate users via LDAP but authorise them via database. It is a common solution – we make sure that only company’s users are logging into app, but there comes flexibility with ACL stored locally. In Grails it looked pretty simple until I started to integrate this solution into my application. It took me a while to put everything together so I decided to share it.

To make long things short – there is an offical documentation but IMHO, it should be tweaked a little to be more user-friendly. The most important thing to understand are sides and roles that take place in logging process. There is LDAP instance, where we send requests to authorise user. LDAP response must be transmitted to our app and full our users’ object. Meanwhile there is also roles read from database. In addition there is simple check – if logging user has no account in our app, we will create it with default roles.

My app uses simple domain classes provided by Spring Security (User, Role and UserRole). If You are not familiar with them I suggest reading official docs. First we create UserMappingDetails class, which is simple POJO that will store user data (login, password, account data) and authorities (roles that user has).

class ChlebikUserDetails extends GrailsUser {

   ChlebikUserDetails(String username, String password, boolean enabled,
                 boolean accountNonExpired, boolean credentialsNonExpired,
                 boolean accountNonLocked,
                 Collection<GrantedAuthority> authorities,
                 long id, String fullName) {
      super(username, password, enabled, accountNonExpired,
            credentialsNonExpired, accountNonLocked, authorities, id)      
   }
}

Next we create mapping class, which will translate LDAP response to our application user.

class ChlebikUserDetailsContextMapper implements UserDetailsContextMapper {

	private static final List NO_ROLES = [new SimpleGrantedAuthority(SpringSecurityUtils.NO_ROLE)]
		
	@Override
	@Transactional
	public ChlebikUserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<SimpleGrantedAuthority> authority) {
		
		User user = User.findByUsername(username)
		
		if(!user) {					
				// Create new user and save to the database                                
				user = new User()
				user.username = username				
				user.password = "123" // doesn't matter
				user.save(flush: true, failOnError: true)
									
				UserRole userRole = new UserRole()
				userRole.user = user
				userRole.role = Role.findByAuthority('USER') // Default role in my app
				userRole.save(flush: true, failOnError: true)			
		}
						 
		def authorities = user.getAuthorities().collect { new SimpleGrantedAuthority(it.authority) }		
		def userDetails = new ChlebikUserDetails(username, user.password, user.enabled, false,
					false, false, authorities, user.id, username)
		return userDetails
	}

	
	@Override
	public void mapUserToContext(UserDetails arg0, DirContextAdapter arg1) {}	
}

Ok, we are getting closer. Last class to create is service that will be called by Spring Security to retrieve our user when needed. It cannot be put in Grails’ service directory!!! Just place it in src/groovy

class PrePopulateUserDetailsService implements GrailsUserDetailsService  {
	
	Logger logger = Logger.getLogger(getClass())
	LdapUserDetailsService ldapUserDetailsService
	
	static final List NO_ROLES = [new SimpleGrantedAuthority(SpringSecurityUtils.NO_ROLE)]
	
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
		return loadUserByUsername(username, true)
	}
	
	@Override
	@Transactional	// Services in Grails are transactional by default but it is normal class so we put this annotation
	public UserDetails loadUserByUsername(String username, boolean loadRoles) throws UsernameNotFoundException, DataAccessException {
				
		User user = User.findByUsername(username)
		def authorities = user.getAuthorities().collect {new SimpleGrantedAuthority(it.authority)}
		
		return new ChlebikUserDetails(user.username, user.password, user.enabled,
			!user.accountExpired, !user.passwordExpired,
			!user.accountLocked, authorities ?: NO_ROLES, user.id,
			user.username)   
	}
}

That’s all. Of course we need to add some config to our application. First we visit configuration folder and spring subfolder. There in resources.groovy we put this (registering beans):

beans = {		
	ldapUserDetailsMapper(com.wordpress.chlebik.ChlebikUserDetailsContextMapper)
	userDetailsService(com.wordpress.chlebik.PrePopulateUserDetailsService)
}

And in out Config.groovy (or whatever user-defined config file You are using) we should have several config properties. I am putting them all (to allow Grails connect to LDAP).

grails.plugin.springsecurity.providerNames = ['rememberMeAuthenticationProvider', 'ldapAuthProvider', 'anonymousAuthenticationProvider']

// Probably better to keep this data in an external file for security reasons
grails.plugin.springsecurity.ldap.context.managerDn = ''
grails.plugin.springsecurity.ldap.context.managerPassword = ''
grails.plugin.springsecurity.ldap.context.server = ''

grails.plugin.springsecurity.ldap.authorities.ignorePartialResultException = true // typically needed for Active Directory
grails.plugin.springsecurity.ldap.search.base = 'CN=putwhatyoumust,O=putwhatyoumust'
grails.plugin.springsecurity.ldap.authenticator.dnPatterns=='uid={0},CN=putwhatyoumust,O=putwhatyoumust'
grails.plugin.springsecurity.ldap.search.filter="uid={0}" 
grails.plugin.springsecurity.ldap.search.searchSubtree = true
grails.plugin.springsecurity.ldap.auth.hideUserNotFoundExceptions = false

// These are crucial for LDAP/DB configuration
grails.plugin.springsecurity.ldap.mapper.userDetailsClass='com.wordpress.chlebik.ChlebikUserDetails'
grails.plugin.springsecurity.ldap.authorities.retrieveGroupRoles = false
grails.plugin.springsecurity.ldap.authorities.retrieveDatabaseRoles = true

And it magically works. Above code is the result of several hours on the web. Below I put all links that helped me a lot.

Grails passwords salted
Juan Vazquez GitHub
Most helpfull Nabble
Customizing authentication in your grails app
Official plugin page