注入LdapTemplate以返回Grails服务内的用户详细信息会导致Null指针异常

时间:2012-02-04 15:23:09

标签: grails spring-security ldap spring-ldap

我一直在努力使用Spring Security LDAP一段时间了,就在我终于认为我被击败时,它再次绊倒了我。

场景:我让用户使用他们的组织凭据登录,然后我会检查内部用户数据库。如果它们不存在,我在本地创建它们然后设置它们的本地权限(我不能触摸LDAP服务器,只能对它进行身份验证 - 所以我不能在那里添加权限)。这很好......但是我想在LDAP中添加几个字段 - 它们的全名和电子邮件地址,这就是它出错的地方。

我在控制器中进行LDAP搜索 - 使用以下代码(我已经进一步注入了ldapTemplate):

def fullName = ldapTemplate.search("", "(uid=" + uid + "*)", new AttributesMapper() {
        @Override
        public Object mapFromAttributes(Attributes attrs) throws NamingException {
            return attrs.get("cn").get()
        }
    })

这完美无缺。但是,当我在一个名为后验证的服务中复制此代码时,ldapTemplate始终为null ...我尝试了一些不同的东西,但是我无法让它正确填充...任何人都可以解决这个问题为什么?我希望自从凌晨4点21分起我正在做一些愚蠢的事情,我应该在大约6小时前躺在床上......

编辑:这是服务代码的要求,感谢看看Burt - 它目前不是非常强大,因为我没有让它工作过去只是创建一个新的本地用户 - 还有工作要做。

package com.myPackage

import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
import org.springframework.ldap.core.AttributesMapper
import org.springframework.security.core.Authentication
import org.springframework.security.core.authority.GrantedAuthorityImpl
import org.springframework.security.web.authentication.AuthenticationSuccessHandler
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler

import org.apache.commons.lang.RandomStringUtils

class PostAuthHandlerService implements AuthenticationSuccessHandler {

def springSecurityService
def ldapTemplate

private AuthenticationSuccessHandler target = new SavedRequestAwareAuthenticationSuccessHandler();
private List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]

public void onAuthenticationSuccess(HttpServletRequest request,
        HttpServletResponse response, Authentication auth) {
    def username = auth.principal.getAt("username")
    User.withTransaction { status ->
        // Check to see if this user exists in the local db
        def user = User.findByUsername(username)
        if (!user) { // User doesn't exist yet, so create and make a user...
            def userRole = Role.findByAuthority('ROLE_USER') ?:
                    new Role(authority: 'ROLE_AM').save(failOnError: true)
            user = new User(
                    username: username,
                    password: auth.getCredentials() ?: placeholderPassword(),
                    displayName: getLdapDetails("username", "cn") ?: "",
                    email: getLdapDetails("username", "mail") ?: "",
                    enabled: true).save(failOnError: true)
            UserRole.create user, userRole
        }
        else {
            println("--- You exist already! Updating details")
            user.displayName = getLdapDetails("username", "cn") ?: ""
        }
        target.onAuthenticationSuccess(request, response, auth)
    }
}

def getLdapDetails(username, attr) {
    return ldapTemplate.search("", "(uid=$username*)", new AttributesMapper() {
        @Override
        public Object mapFromAttributes(Attributes attrs) throws NamingException {
            return attrs.get(attr).get()
        }
    })
}

def placeholderPassword () {
    // This is here because we also allow local logins for some users.  
    // If the password is not available, then create a big ugly one...
    return org.apache.commons.lang.RandomStringUtils.randomAlphanumeric(128)
}

public void proceed(HttpServletRequest request,
HttpServletResponse response, Authentication auth) {
    target.onAuthenticationSuccess(request, response, auth)
}

}

第二编辑:我一直在尝试各种不同的东西 - 包括尝试使用springSecurityService.reauthenticate来获取在会话期间使用的本地用户而不是LDAP - 并且这个bean也是空的...它好像我根本无法将任何豆子注入我的服务中。

我最终发现这篇文章:http://burtbeckwith.com/blog/?p=993给了我一个解决方法,我现在让它工作......但我仍然想知道它为什么不首先......我有在Grails中学到很多 - 而且很难知道从哪里开始。

提前干杯

史蒂夫

1 个答案:

答案 0 :(得分:2)

你是如何注入authenticationSuccessHandler的?您应该尝试在resources.xml中定义authenticationSuccessHandler

Grails 1.3.5 and Spring Security Core