/** /* Copyright 2006-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.codehaus.groovy.grails.plugins.springsecurity import org.apache.log4j.Logger import org.springframework.security.GrantedAuthority import org.springframework.security.GrantedAuthorityImpl import org.springframework.security.userdetails.UserDetails import org.springframework.security.userdetails.UserDetailsService import org.springframework.security.userdetails.UsernameNotFoundException import org.springframework.dao.DataAccessException /** * {@link UserDetailsService} with {@link GrailsDomainClass} Data Access Object. * @author Tsuyoshi Yamamoto * @author Burt Beckwith */ class GrailsDaoImpl extends GrailsWebApplicationObjectSupport implements UserDetailsService { private final Logger logger = Logger.getLogger(getClass()) def authenticateService // dependency-injected fields String loginUserDomainClass String usernameFieldName String passwordFieldName String enabledFieldName String relationalAuthoritiesField String authorityFieldName String authoritiesMethodName /** * {@inheritDoc} * @see org.springframework.security.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) */ UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { return loadUserByUsername(username, true) } /** * Load a user by username, optionally not loading roles. * @param username the login name * @param loadRoles if true load roles from the database * @return the user if found, otherwise throws {@link UsernameNotFoundException} * @throws UsernameNotFoundException if the user isn't found * @throws DataAccessException if there's a database problem */ UserDetails loadUserByUsername(String username, boolean loadRoles) throws UsernameNotFoundException, DataAccessException { if (authenticateService.securityConfig.security.useNtlm) { username = username.toLowerCase() } GrailsWebApplicationObjectSupport.SessionContainer container = setUpSession() try { def user = loadDomainUser(username, container.session) GrantedAuthority[] authorities = loadAuthorities(user, username, loadRoles) return createUserDetails( username, user."$passwordFieldName", user."$enabledFieldName", authorities, user) } finally { releaseSession(container) } } protected GrantedAuthority[] loadAuthorities(user, String username, boolean loadRoles) { if (!loadRoles) { return [] } if (relationalAuthoritiesField) { return createRolesByRelationalAuthorities(user, username) } if (authoritiesMethodName) { return createRolesByAuthoritiesMethod(user, username) } logger.error("User [${username}] has no GrantedAuthority") throw new UsernameNotFoundException("User has no GrantedAuthority") } protected def loadDomainUser(username, session) throws UsernameNotFoundException, DataAccessException { List users = session.createQuery( "from $loginUserDomainClass where $usernameFieldName=:username") .setString('username', username) .setCacheable(true) .list() if (users.empty) { logger.error "User not found: $username" throw new UsernameNotFoundException("User not found", username) } return users[0] } /** * Create the {@link UserDetails} instance. Subclasses can override to inherit core functionality * but determine the concrete class without reimplementing the entire class. * @param username the username * @param password the password * @param enabled set to true if the user is enabled * @param authorities the authorities that should be granted to the caller * @param user the user domain instance * @return the instance */ protected UserDetails createUserDetails( String username, String password, boolean enabled, GrantedAuthority[] authorities, Object user) { new GrailsUserImpl( username, password, enabled, true, true, true, authorities, user) } protected GrantedAuthority[] createRolesByAuthoritiesMethod(user, String username) { Set authorities = user."$authoritiesMethodName"() assertNotEmpty authorities, username authorities.collect { roleName -> new GrantedAuthorityImpl(roleName) } as GrantedAuthority[] } protected GrantedAuthority[] createRolesByRelationalAuthorities(user, String username) { // get authorities from LoginUser [LoginUser]--M:M--[Authority] Set authorities = user."$relationalAuthoritiesField" assertNotEmpty authorities, username authorities.collect { item -> new GrantedAuthorityImpl(item."$authorityFieldName") } as GrantedAuthority[] } protected void assertNotEmpty(Collection authorities, String username) { if (authorities == null || authorities.empty) { logger.error("User [${username}] has no GrantedAuthority") throw new UsernameNotFoundException("User has no GrantedAuthority") } } protected Logger getLog() { return logger } }