如何将 LDAP 用户与 Grails 中 Spring Security 创建的 PERSON 表集成?

2023-12-07

我们正在创建一个 grails 应用程序,我们希望用户使用其 Active Directory 凭据登录。此外,我们希望使该应用程序的企业所有者能够控制谁有权访问某些链接(操作)。因此,我们在 grails 应用程序中使用以下插件:

  1. Spring安全核心
  2. Spring 安全 LDAP
  3. Spring安全UI

因为我们希望授权业务用户在必要时动态创建具有某些权限(操作)的自定义角色,所以我们认为最好的 Spring Security 配置是基于Requestmap数据库的方法

到目前为止我们已经完成了以下工作:

  • 我们能够成功地针对 Active Directory 进行身份验证。
  • 我们还可以通过 spring-security-ui 插件的 UI 界面为不同的角色(ROLE_XXX)创建不同的请求映射

问题/疑问

spring-security-core 插件创建了下表:

  • PERSON
  • 权威
  • PERSON_AUTHORITY
  • 请求地图

这些表支持创建角色以及将 URL 分配给角色。然而,Person_Authoritity 表作为约定名称意味着它是人员和权限(角色)之间的多对多关系,因为一个人可能拥有多个角色。我的问题是我没有“人员”,因为该人员已存在于 Active Directory(外部源)中,并且不是在应用程序中创建的。

有没有办法让经过身份验证的用户成为 PERSON ? spring security 解决方案需要 Person 行或对象,但是您更喜欢引用它。

我也在这里发布了问题:

http://grails.1312388.n4.nabble.com/Issues-integrating-LDAP-Authentication-with-Requestmap-to-Secure-URLs-td4644040.html

Thanks,


因此,您基本上需要将 AD 用户映射到人员。

这是 src/groovy 中需要的 3 个类。显然根据需要修改它们:

    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) {
    }
}

在 spring/resources.groovy 中配置:

import yourpackagenamehere.CustomUserDetailsService
import yourpackagenamehere.CustomUserDetailsContextMapper
beans = {
    userDetailsService(CustomUserDetailsService)

    ldapUserDetailsMapper(CustomUserDetailsContextMapper) {
        dataSource = ref("dataSource")
    }
}

在 Config.groovy 下,这是我的设置:

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}' 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将 LDAP 用户与 Grails 中 Spring Security 创建的 PERSON 表集成? 的相关文章

随机推荐