在grails 2.2.4 spring security core 2.0中配置ldap?

Posted

技术标签:

【中文标题】在grails 2.2.4 spring security core 2.0中配置ldap?【英文标题】:Configure ldap in grails 2.2.4 spring security core 2.0? 【发布时间】:2014-02-14 02:16:34 【问题描述】:

我目前正在将我的应用程序与公司 ldap 集成。虽然我能够让应用程序实际检查 ldap 上的用户进行身份验证,但用户无法克服 Spring Security ROLES 配置。我越来越: “拒绝 抱歉,您无权查看此页面。” 每次我尝试进入带有 @Secured(['ROLE_USER']) 的页面时。我想知道如何将 LDAP 上的每个用户添加为 ROLE_USER,以便他能够充分使用应用程序。

我的 ldap 配置很简单:

grails.plugin.springsecurity.providerNames = ['ldapAuthProvider','anonymousAuthenticationProvider','rememberMeAuthenticationProvider']
grails.plugin.springsecurity.ldap.context.anonymousReadOnly = true
grails.plugin.springsecurity.ldap.context.server = "SOME LDAP ADRESS"
grails.plugin.springsecurity.ldap.authorities.groupSearchBase = 'ou=Employees,O=*****,C=****'

grails.plugin.springsecurity.ldap.search.base = 'O=****,C=****'
grails.plugin.springsecurity.ldap.authorities.retrieveGroupRoles = true
grails.plugin.springsecurity.ldap.authorities.retrieveDatabaseRoles = true
grails.plugin.springsecurity.ldap.authorities.groupSearchFilter = 'member=0'
grails.plugin.springsecurity.ldap.search.attributesToReturn = null

spring security core是默认的:

// Added by the Spring Security Core plugin:
grails.plugin.springsecurity.userLookup.userDomainClassName = 'amelinium1.grails.SecUser'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'amelinium1.grails.SecUserSecRole'
grails.plugin.springsecurity.authority.className = 'amelinium1.grails.SecRole'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
    '/**':                              ['permitAll'],
    '/**/systeminfo':                 ['permitAll'],
    '/**/js/**':                      ['permitAll'],
    '/**/css/**':                     ['permitAll'],
    '/**/images/**':                  ['permitAll']]
grails.plugin.springsecurity.logout.postOnly = false

http://grails-plugins.github.io/grails-spring-security-core/docs/manual/guide/single.pdf 上提供的文档似乎不是最新的,即使它是针对 2.0 版本的 spring security core。 我尝试实现 Custom GrailsUser 和 GrailsUserDetailsS​​ervice,但它们似乎与插件的其余部分没有融合。(基于文档的实现)。

任何人都可以通过一些关于如何在最新版本 2.0-RC2 中实现 LDAP 的信息来指出正确的方向吗?

编辑

我的 CustomUserDetailsS​​ervice 类,但我不确定它的 LDAP 配置是否正确:

    class CustomUserDetailsService implements GrailsUserDetailsService

    @Override
    public 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
    

    @Override
    public UserDetails loadUserByUsername(String username, boolean loadRoles)
            throws UsernameNotFoundException, DataAccessException 

        return loadUserByUsername(username);
    


还有 CustomUserDetails 类:

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
        
    

问题是我无法从 LDAP 获取其他信息,而不是用户名作为 ldap 登录。 也希望在这里得到帮助。在将应用程序重新设计为基于 Customclasses 后,我收到如下错误: 方法没有签名:静态 org.springframework.security.core.userdetails.User.findByUsername() 适用于参数类型:(java.lang.String) 值:[hajduk]

【问题讨论】:

【参考方案1】:

默认情况下,Spring Security 插件从数据库中获取用户和角色数据。负责读取用户和角色数据的 Spring bean 名为userDetailsService。如果您想从其他地方获取您的用户和角色数据 - 例如LDAP - 你只需要用你自己的替换这个 bean,例如

import org.springframework.security.core.userdetails.*
import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.springframework.dao.DataAccessException

class LdapUserDetailsService implements UserDetailsService 

    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException 
        // load the user and their role(s) from LDAP by username and return their 
        // details as an instance of a class that implements the UserDetails interface
    

别忘了在resources.groovy中注册这个类为Spring bean

userDetailsService(LdapUserDetailsService)

有一些插件可以将 Spring Security 与 LDAP 集成,但我更愿意自己做,因为它很简单。文档提供了自定义UserDetailsService 的an example。请注意,在编写自己的 UserDetailsService/UserDetails 实现时,没有必要扩展任何特定的类,为了调试,直接实现接口可能更容易。

【讨论】:

嘿,谢谢回复。由于我的 ldap 没有配置自己的角色,我设法通过为 ldap 提供我自己的 AuthoritiesPopulator 实现应用程序来克服身份验证问题。像这样: ldapAuthProvider(org.springframework.security.ldap.authentication.LdapAuthenticationProvider, ref("ldapAuthenticator"), ref("authoritiesPopulator") ) authorityPopulator(amelinium1.grails.CustomAuthoritiesPopulator) 目前用户可以使用 ldap 登录并使用应用程序的安全部分,但我希望能够将更多 ldap 字段映射到我的 UserDetails 类。目前 springSecurityService.getPrinsipal() 仅返回给定用户的 LOGIN 。但我想使用更多像 FirstName LastName、email 等。我从文档中阅读了我必须实现自己的 UserDetailsS​​ervice 和 UserDetailsContextMapper 并将它们注册为 ldapUserDetailsMapper,但我不知道如何在默认 ContextMapper 中获取数据并转发它其余的课程。关于这个问题的任何想法? 如果您编写自己的UserDetailsService 实现并返回UserDetails 的自定义实现,您可以将任意数量的字段映射到后者。这正是本示例所演示的内容:grails-plugins.github.io/grails-spring-security-core/docs/…。您可以通过调用 springSecurityService.currentUser 为当前用户检索 UserDetails 实现的实例 我已经添加了我的自定义类,但我真的不知道如何在详细信息类中从 ldap 获取数据。 @user2761900 然后发布一个新问题,询问如何执行此操作

以上是关于在grails 2.2.4 spring security core 2.0中配置ldap?的主要内容,如果未能解决你的问题,请参考以下文章

grails acegi 迁移到 spring-security-core

在grails 2.2.4 spring security core 2.0中配置ldap?

如何保护使用 Azure 和 Oauth 的 grails API?

Grails 2.3.4 池为空。无法在 30 秒内获取连接

从 2.1 升级到 2.2.4 后 Grails 自动编译中断

Grails 2.2.4:瞬态属性:为啥自定义验证器被调用两次?