注入LdapTemplate以在Grails服务中返回用户详细信息会导致空指针异常 [英] Injecting LdapTemplate to return user details inside a Grails service causes Null Pointer Exception

查看:173
本文介绍了注入LdapTemplate以在Grails服务中返回用户详细信息会导致空指针异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用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()
}
})

这完美的作品。但是当我在一个称为post-authentication的服务中复制这段代码时,ldapTemplate总是为空......我尝试了一些不同的东西,但是我无法让它正确地填充......任何人都可以点亮一些光为什么?我希望自从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
$ b $ class PostAuthHandlerService实现AuthenticationSuccessHandler {

def springSecurityService
def ldapTemplate

private AuthenticationSuccessHandler target = new SavedRequestAwareAuthenticationSuccessHandler();
private List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]
$ b $ public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,Authentication auth){
def username = auth.principal.getAt(username)
User.withTransaction {status - >
//检查这个用户是否存在于本地数据库
def user = User.findByUsername(username)
if(!user){//用户还不存在,所以创建并创建用户...
def userRole = Role.findByAuthority('ROLE_USER')?:
新角色(权限:'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.o nAuthenticationSuccess(request,response,auth)
}
}
$ b def getLdapDetails(username,attr){
return ldapTemplate.search(,(uid = ()),new AttributesMapper(){
@Override
public Object mapFromAttributes(Attributes attrs)throws NamingException {
return attrs.get(attr).get()
}
})
}

def placeholderPassword(){
//这是因为我们也允许某些用户的本地登录。
//如果密码不可用,那么创建一个很丑的...
return org.apache.commons.lang.RandomStringUtils.randomAlphanumeric(128)
}

public void proceed(HttpServletRequest请求,
HttpServletResponse响应,身份验证身份验证){
target.onAuthenticationSuccess(请求,响应,身份验证)
}

}

编辑:我一直在尝试各种不同的东西 - 使用springSecurityService.reauthenticate来获取在会话期间使用本地用户而不是LDAP - 而且这个bean也是空的......好像我不能在我的服务中注入任何bean。



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



提前喝彩

Steve

解决方案

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

Grails 1.3.5和Spring Security Core


I've been struggling with Spring Security LDAP for a while now, and just when I finally thought I had it beaten into submission, its tripped me up again.

The scenario: I'm having users log in using their organisation credentials, which I then check against the internal user database. If they don't exist, I create them locally and then set their local authorities (I can't touch the LDAP server, only authenticate against it - so I can't add the authorities there). This works fine... but I then want to add a couple of fields from LDAP - their full name and email address, and this is where it goes wrong.

I have LDAP searches working in a controller - using the following code (I've injected ldapTemplate further up):

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

and this works perfectly. But when I replicate this code in a service that is called post-authentication the ldapTemplate is always null... I've tried a few different things, but I can't get it to populate properly... can anyone shed some light on why? I'm hoping its something stupid I'm doing since its 4:21am and I should have been in bed about 6 hours ago...

EDIT: Here is the service code as requested, thanks for taking a look Burt - its currently not very robust as I haven't got it working past simply creating a new local user - there is work to do on it yet.

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

}

2nd Edit: I've been trying various different things - including trying to use springSecurityService.reauthenticate to get the local user to be used during the session rather than the LDAP one - and this bean is null as well... it seems like I can't inject any beans into my service at all.

I eventually found this post: http://burtbeckwith.com/blog/?p=993 which gave me a workaround and I now have it working... but I'd still like to know why it didn't in the first place... I have so much to learn in Grails - and its hard to know where to start.

Cheers in advance

Steve

解决方案

How are you injecting authenticationSuccessHandler ? You should try defining authenticationSuccessHandler in resources.xml

Grails 1.3.5 and Spring Security Core

这篇关于注入LdapTemplate以在Grails服务中返回用户详细信息会导致空指针异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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