How to integrate an LDAP user with the PERSON table created by Spring Security in Grails?

前端 未结 1 1695
攒了一身酷
攒了一身酷 2021-01-16 01:34

We are creating a grails aplication where we want the user to log in using their Active Directory credentials. Additionally, we want to give the business owner of this appli

相关标签:
1条回答
  • 2021-01-16 02:31

    So you need to essentially map the AD user to a Person.

    Here are the 3 classes you need in src/groovy. Obviously modify them as needed:

        package yourpackagename
    
        import org.codehaus.groovy.grails.plugins.springsecurity.GrailsUser
        import org.springframework.security.core.GrantedAuthority
    
        class CustomUserDetails extends GrailsUser{
            final String firstName
            final String lastName
    
            CustomUserDetails(String username, String password, boolean enabled,
                              boolean accountNonExpired, boolean credentialsNonExpired,
                              boolean accountNonLocked,
                              Collection<GrantedAuthority> authorities,
                              long id, String firstName, String lastName) {
                super(username, password, enabled, accountNonExpired,
                        credentialsNonExpired, accountNonLocked, authorities, id)
    
                this.firstName = firstName
                this.lastName = lastName
            }
        }
    
    package yourpackagenamehere
    
    import org.codehaus.groovy.grails.plugins.springsecurity.GrailsUserDetailsService
    import org.springframework.security.core.authority.GrantedAuthorityImpl
    import org.springframework.security.core.userdetails.UserDetails
    import org.springframework.security.core.userdetails.UsernameNotFoundException
    import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
    
    class CustomUserDetailsService implements GrailsUserDetailsService {
    
        /**
         * Some Spring Security classes (e.g. RoleHierarchyVoter) expect at least one role, so
         * we give a user with no granted roles this one which gets past that restriction but
         * doesn't grant anything.
         */
        static final List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]
    
        UserDetails loadUserByUsername(String username, boolean loadRoles)
        throws UsernameNotFoundException {
            return loadUserByUsername(username)
        }
    
        UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    
            User.withTransaction { status ->
    
                User user = User.findByUsername(username)
                if (!user) throw new UsernameNotFoundException('User not found', username)
    
                def authorities = user.authorities.collect {new GrantedAuthorityImpl(it.authority)}
    
                return new CustomUserDetails(user.username, user.password, user.enabled,
                        !user.accountExpired, !user.passwordExpired,
                        !user.accountLocked, authorities ?: NO_ROLES, user.id,
                        user.firstName, user.lastName)
            } as UserDetails
        }
    }
    
    package yourpackagenamehere
    
    import groovy.sql.Sql
    
    import org.springframework.ldap.core.DirContextAdapter
    import org.springframework.ldap.core.DirContextOperations
    import org.springframework.security.core.userdetails.UserDetails
    import org.springframework.security.ldap.userdetails.UserDetailsContextMapper
    import org.springframework.security.core.authority.GrantedAuthorityImpl
    import org.springframework.security.core.GrantedAuthority
    import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
    
    import org.springframework.security.core.userdetails.UsernameNotFoundException
    import org.springframework.security.authentication.DisabledException
    
    class CustomUserDetailsContextMapper implements UserDetailsContextMapper {
    
        private static final List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]
    
        def dataSource
    
        @Override
        public CustomUserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<GrantedAuthority> authority) {
    
            username = username.toLowerCase()
    
            User user = User.findByUsername(username)
    
            String firstName = ctx.originalAttrs.attrs['givenname'].values[0]
            String lastName = ctx.originalAttrs.attrs['sn'].values[0]
    
    
            def roles
    
            User.withTransaction {
    
                if(!user){
                    user = new User(username: username, enabled: true, firstName: firstName, lastName: lastName)
                    user.save(flush: true)
                }
                else {
                    user = User.findByUsername(username)
                    user.firstName = firstName
                    user.lastName = lastName
                    user.save(flush: true)
                }
    
                roles = user.getAuthorities()
            }
    
            if ( !user.enabled )
                throw new DisabledException("User is disabled", username)
    
    
            def authorities = roles.collect { new GrantedAuthorityImpl(it.authority) }
            authorities.addAll(authority)
            def userDetails = new CustomUserDetails(username, user.password, user.enabled, false, false, false, authorities, user.id, user.firstName, user.lastName)
    
            return userDetails
        }
    
        @Override
        public void mapUserToContext(UserDetails arg0, DirContextAdapter arg1) {
        }
    }
    

    Under configuration in spring/resources.groovy :

    import yourpackagenamehere.CustomUserDetailsService
    import yourpackagenamehere.CustomUserDetailsContextMapper
    beans = {
        userDetailsService(CustomUserDetailsService)
    
        ldapUserDetailsMapper(CustomUserDetailsContextMapper) {
            dataSource = ref("dataSource")
        }
    }
    

    Under Config.groovy, here are my settings:

    grails.plugins.springsecurity.ldap.context.managerDn = 'CN=username,OU=People,DC=foo,DC=com'
    grails.plugins.springsecurity.ldap.context.managerPassword = 'password'
    grails.plugins.springsecurity.ldap.context.server = 'ldap://foo.com:389/'
    grails.plugins.springsecurity.ldap.authorities.ignorePartialResultException = true
    grails.plugins.springsecurity.ldap.search.base = 'ou=People,dc=foo,dc=com'
    grails.plugins.springsecurity.ldap.search.filter="sAMAccountName={0}"
    grails.plugins.springsecurity.ldap.search.searchSubtree = true
    grails.plugins.springsecurity.ldap.auth.hideUserNotFoundExceptions = false
    grails.plugins.springsecurity.ldap.search.attributesToReturn = null
    grails.plugins.springsecurity.providerNames = ['ldapAuthProvider', 'anonymousAuthenticationProvider']
    grails.plugins.springsecurity.ldap.mapper.userDetailsClass = 'CustomUserDetails'
    
    grails.plugins.springsecurity.ldap.authorities.retrieveGroupRoles = true
    grails.plugins.springsecurity.ldap.authorities.retrieveDatabaseRoles = true
    grails.plugins.springsecurity.ldap.authorities.groupSearchBase ='dc=foo,dc=com'
    grails.plugins.springsecurity.ldap.authorities.groupSearchFilter = 'member={0}' 
    
    0 讨论(0)
提交回复
热议问题