Grails Spring Security:如何将自己的用户域用于我的LdapAuthenticator?

时间:2015-03-09 10:13:00

标签: grails spring-security ldap

我正在使用Spring Security Ldap插件。

我有自己的用户域,只有username和userId列。我想使用LDAP中的用户名和密码对其进行身份验证,并检查用户名是否存在于数据库中。

域名:用户名是我用于登录的用户名

class User {
    String username
    String userId

    static mapping = {
        id name: 'userId'
        version: false
        id generator: 'assigned'
    }

    static constrainsts = {
        userId blank: false, nullable: false, size:1..12
        username blank: false, unique: true, size:1..12
    }
}

自定义UserDetailsContextMapper:

class CustomUserDetailsContextMapper implements UserDetailsContextMapper {

    def springSecurityService

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

    @Override
    @Transactional
    UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<SimpleGrantedAuthority> authority) {
        SecUser user = SecUser.findByUsername(username)

        if (!user) throw new UsernameNotFoundException('User not found', username)

        return new CustomUserDetails(
            user.userid, username
            )
    }

    @Override
    public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
        throw new IllegalStateException("Only retrieving data from LDAP is currently supported")
    }
}

自定义用户详细信息:

class CustomUserDetails extends GrailsUser {
    private final Object _id;

   public CustomUserDetails(
         String userId, String username) {

      super(username, password, enabled, accountNonExpired,
            credentialsNonExpired, accountNonLocked, authorities, userId);
   }

   public Object getDomainClass() {
      return null;
   }

}

我能够验证在Active Directory中可用但在数据库中不存在的用户。它返回“未找到用户”。 但是在验证Active Directory和数据库中可用的用户时,我收到“构造函数不匹配”的错误

这是我遇到的错误......

[/sampleproject].[default] Servlet.service() for servlet [default] in context with path [/sampleproject] threw exception
groovy.lang.GroovyRuntimeException: Could not find matching constructor for: com.security.CustomUserDetails(java.lang.String, null, java.lang.Boolean, java.lang.Boolean, java.lang.Boolean, java.lang.Boolean, null, java.lang.String)
    at groovy.lang.MetaClassImpl.invokeConstructor(MetaClassImpl.java:1723)
    at groovy.lang.MetaClassImpl.invokeConstructor(MetaClassImpl.java:1526)
    at groovy.lang.ExpandoMetaClass.invokeConstructor(ExpandoMetaClass.java:675)
    at org.codehaus.groovy.runtime.callsite.MetaClassConstructorSite.callConstructor(MetaClassConstructorSite.java:46)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:57)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:182)
    at com.security.CustomUserDetailsContextMapper.mapUserFromContext(CustomUserDetailsContextMapper.groovy:41)
    at com.security.CustomUserDetailsContextMapper$$FastClassBySpringCGLIB$$f40634de.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:708)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)
    at com.security.CustomUserDetailsContextMapper$$EnhancerBySpringCGLIB$$e13e0669.mapUserFromContext(<generated>)
    at org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:63)
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
    at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
    at grails.plugin.springsecurity.web.authentication.RequestHolderAuthenticationFilter.attemptAuthentication(RequestHolderAuthenticationFilter.java:76)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:211)
    at grails.plugin.springsecurity.web.authentication.RequestHolderAuthenticationFilter.doFilter(RequestHolderAuthenticationFilter.java:49)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter.doFilter(MutableLogoutFilter.java:82)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:69)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.codehaus.groovy.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

1 个答案:

答案 0 :(得分:0)

我假设您做了一些更改以删除专有信息和/或简化代码,但就像目前一样,CustomUserDetails类非常破碎。

类名是CustomUserDetails,你看似是一个构造函数,除了它的名字是UAMSUserDetailsGrailsUser具有id属性,其构造函数签名为

public GrailsUser(String username, String password, boolean enabled,
                  boolean accountNonExpired, boolean credentialsNonExpired,
                  boolean accountNonLocked,
                  Collection<GrantedAuthority> authorities, Object id)

因此,您对super的调用无效 - 参数计数错误(您没有将userId作为id传递)而password没有enabled,{ {1}},accountNonExpiredcredentialsNonExpiredaccountNonLockedauthorities已定义。假设你想要默认值,不应该是这样的吗?

class UAMSUserDetails extends GrailsUser {

   UAMSUserDetails(String userId, String username) {
      super(username, null/*password*/, true, true, true, true,
            null/*authorities*/, userId)
   }

   def getDomainClass() { null }
}