如何将LDAP用户与Spring Security在Grails中创建的PERSON表集成在一起? [英] How to integrate an LDAP user with the PERSON table created by Spring Security in Grails?

查看:215
本文介绍了如何将LDAP用户与Spring Security在Grails中创建的PERSON表集成在一起?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在创建一个grails应用程序,我们希望用户使用其Active Directory凭据登录。此外,我们希望赋予此应用程序的业主拥有控制访问某些链接(操作)的权限的能力。因此,我们在我们的grails应用程序中使用了以下插件:
$ b


  1. Spring Security Core

  2. Spring Security LDAP

  3. Spring Security UI

因为我们希望授权业务用户创建我们认为最好的Spring Security Configuration是基于Request Map数据库的方法

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


  • 我们可以成功地对Active Directory进行身份验证。

  • 我们还可以通过spring-security-ui插件的UI界面为不同的角色(ROLE_XXX)创建不同的请求映射。





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


  • PERSON

  • AUTHORI TY

  • PERSON_AUTHORITY

  • REQUESTMAP



  • 这些是支持创建角色的表格,将URL分配给角色。然而,作为约定名称的Person_Authoritity表意味着它是PERSON和AUTHORITY(ROLE)之间的多对多关系,因为一个人可能具有多个角色。我的问题是我没有Person,因为这个人已经存在于Active Directory(外部源)中,并且它没有在应用程序中创建。

    有没有办法让认证用户成为PERSON?弹簧安全解决方案需要Person行或对象,但是您更愿意引用它。



    我也在这里发布了这个问题:



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



    感谢,

    解决方案

    因此,您需要将AD用户映射到Person。



    以下是您在src / groovy中需要的3个类。显然可以根据需要修改它们:

      package yourpackagename 

    import org.codehaus.groovy.grails.plugins .springsecurity.GrailsUser
    import org.springframework.security.core.GrantedAuthority
    $ b 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> authority,
    long id,String firstName ,String lastName){
    super(用户名,密码,启用,accountNonExpired,
    credentialsNonExpired,accountNonLocked,权限,id)

    this.firstName = firstName
    this。 lastName = last名称
    }
    }

    包yourpackagenamehere

    导入org.codehaus.groovy.grails.plugins.springsecurity.GrailsUserDetailsS​​ervice
    导入组织。 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

    类CustomUserDetailsS​​ervice实现了GrailsUserDetailsS​​ervice {
    $ b $ / **
    *一些Spring Security类(例如RoleHierarchyVoter)期望至少有一个角色,所以
    *我们给予一个没有授予角色的用户,这个角色超过了这个限制,但是
    *没有授予任何东西。
    * /
    static final List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]
    $ b $ UserDetails loadUserByUsername(String username,boolean loadRoles)
    throws UsernameNotFoundException {
    return loadUserByUsername(username)
    }
    $ b $ 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)}

    返回新的CustomUserDetails(user.username,user.password,user.enabled,
    !user.accountExpired,!user.passwordExpired ,
    !user.accountLocked,authority?:NO_ROLES,user.id,
    user.firstName,user.lastName)
    }作为UserDetails
    }
    }

    package yourpackagenamehere here

    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.springframew ork.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

    类CustomUserDetailsContextMapper实现UserDetailsContextMapper {

    private static final List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]

    def dataSource
    $ b $ @Override
    public CustomUserDetails mapUserFromContext(DirContextOperations ctx,String username,Collection< GrantedAuthority>权限){

    用户名= username.toLowerCase()

    用户用户= User.findByUsername(用户名)

    字符串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)
    抛出新的DisabledException(用户被禁用,用户名)


    def authorities = roles.collect {new GrantedAuthorityImpl(it.authority)}
    authorities.addAll(authority)
    def userDetails = new CustomUserDetails(username,user .password,user.enabled,false,false,false,user.id,user.firstName,user.lastName)

    return userDetails
    }

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

    在spring / resources.groovy的配置下:

     导入yourpackagenamehere.CustomUserDetailsS​​ervice 
    导入yourpackagenamehere。 CustomUserDetailsContextMapper
    beans = {
    userDetailsS​​ervice(CustomUserDetailsS​​ervice)

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

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

      grails.plugins.springsecurity.ldap.context.managerDn ='CN = username,OU =人员,DC = foo,DC = com'
    grails.plugins .springsecurity.ldap.context.managerPassword ='密码'
    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.autho rities.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}'


    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 application the ability to control who has access to certain links (actions). Because of this we are using the following plugins in our grails application:

    1. Spring Security Core
    2. Spring Security LDAP
    3. Spring Security UI

    Because we want to empower the business user to create customized roles with certain permissions(actions) on the fly when necessary, we think that the best Spring Security Configuration is the Requestmap database based approach

    So far we have accomplished as follows:

    • We are being able to authenticate against Active Directory successfully.
    • We have also been able to create different Request Mappings for different roles (ROLE_XXX) through the UI interface of the spring-security-ui plugin

    Problems/Questions

    The spring-security-core plugin created the following tables:

    • PERSON
    • AUTHORITY
    • PERSON_AUTHORITY
    • REQUESTMAP

    These are the tables that support the creation of Roles, the assignment of URLs to roles. However, the Person_Authoritity table as the convention name implies it's a many to many relationship between a PERSON and an AUTHORITY (ROLE) since a person can potentially have more than one role. My problem is that I do not have a Person because the person already exists in Active Directory (an external source) and it was not created in the application.

    Is there a way to make the authenticated user to be the PERSON ? The spring security solution requires that Person row or object however you prefer to refer to it.

    I have also posted the question here:

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

    Thanks,

    解决方案

    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}' 
    

    这篇关于如何将LDAP用户与Spring Security在Grails中创建的PERSON表集成在一起?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆