与错误用户

时间:2015-09-22 08:32:22

标签: java spring spring-mvc spring-security

我有一个项目,我使用Spring Boot,Spring Security和Spring MVC。 我将Spring Security配置为使用我们的公司ldap进行身份验证。

当我尝试使用正确的用户登录时,它可以正常工作。但是当我使用错误的密码或错误的用户登录时,它会返回错误:

  

Servlet [dispatcherServlet]的Servlet.service()与path []的上下文引发了异常   java.io.NotSerializableException:com.sun.jndi.ldap.LdapCtx       在java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1183)〜[na:1.7.0_67]       在java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)〜[na:1.7.0_67]       at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)〜[na:1.7.0_67]       在java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)〜[na:1.7.0_67]       在java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)〜[na:1.7.0_67]       在java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)〜[na:1.7.0_67]       at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:440)〜[na:1.7.0_67]       在java.lang.Throwable.writeObject(Throwable.java:985)〜[na:1.7.0_67]       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)〜[na:1.7.0_67]       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)〜[na:1.7.0_67]       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)〜[na:1.7.0_67]       在java.lang.reflect.Method.invoke(Method.java:606)〜[na:1.7.0_67]       在java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)〜[na:1.7.0_67]       在java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1495)〜[na:1.7.0_67]       在java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)〜[na:1.7.0_67]       在java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)〜[na:1.7.0_67]       在java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)〜[na:1.7.0_67]       at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:440)〜[na:1.7.0_67]       在java.lang.Throwable.writeObject(Throwable.java:985)〜[na:1.7.0_67]       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)〜[na:1.7.0_67]       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)〜[na:1.7.0_67]       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)〜[na:1.7.0_67]       在java.lang.reflect.Method.invoke(Method.java:606)〜[na:1.7.0_67]       在java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)〜[na:1.7.0_67]       在java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1495)〜[na:1.7.0_67]       在java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)〜[na:1.7.0_67]       在java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)〜[na:1.7.0_67]       在java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)〜[na:1.7.0_67]       在org.springframework.core.serializer.DefaultSerializer.serialize(DefaultSerializer.java:44)〜[spring-core-4.2.0.RELEASE.jar:4.2.0.RELEASE]       在org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:62)〜[spring-core-4.2.0.RELEASE.jar:4.2.0.RELEASE]       ...省略了46个常见帧   包装方式:org.springframework.core.serializer.support.SerializationFailedException:无法使用DefaultSerializer序列化对象;嵌套异常是java.io.NotSerializableException:com.sun.jndi.ldap.LdapCtx       在org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:67)〜[spring-core-4.2.0.RELEASE.jar:4.2.0.RELEASE]       在org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:34)〜[spring-core-4.2.0.RELEASE.jar:4.2.0.RELEASE]       在org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:50)〜[spring-data-redis-1.6.0.RC1.jar:1.6.0.RC1]       ...省略了44个常用帧   包装方式:org.springframework.data.redis.serializer.SerializationException:无法序列化;嵌套异常是org.springframework.core.serializer.support.SerializationFailedException:无法使用DefaultSerializer序列化对象;嵌套异常是java.io.NotSerializableException:com.sun.jndi.ldap.LdapCtx       在org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:52)〜[spring-data-redis-1.6.0.RC1.jar:1.6.0.RC1]       在org.springframework.data.redis.core.AbstractOperations.rawHashValue(AbstractOperations.java:166)〜[spring-data-redis-1.6.0.RC1.jar:1.6.0.RC1]       在org.springframework.data.redis.core.DefaultHashOperations.putAll(DefaultHashOperations.java:128)~ [spring-data-redis-1.6.0.RC1.jar:1.6.0.RC1]       在org.springframework.data.redis.core.DefaultBoundHashOperations.putAll(DefaultBoundHashOperations.java:85)〜[spring-data-redis-1.6.0.RC1.jar:1.6.0.RC1]       在org.springframework.session.data.redis.RedisOperationsSessionRepository $ RedisSession.saveDelta(RedisOperationsSessionRepository.java:409)〜[spring-session-1.0.1.RELEASE.jar:na]       在org.springframework.session.data.redis.RedisOperationsSessionRepository $ RedisSession.access $ 000(RedisOperationsSessionRepository.java:331)〜[spring-session-1.0.1.RELEASE.jar:na]       在org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:211)〜[spring-session-1.0.1.RELEASE.jar:na]       在org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:141)〜[spring-session-1.0.1.RELEASE.jar:na]       在org.springframework.session.web.http.SessionRepositoryFilter $ SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:187)〜[spring-session-1.0.1.RELEASE.jar:na]       在org.springframework.session.web.http.SessionRepositoryFilter $ SessionRepositoryRequestWrapper.access $ 100(SessionRepositoryFilter.java:163)〜[spring-session-1.0.1.RELEASE.jar:na]       在org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:121)〜[spring-session-1.0.1.RELEASE.jar:na]       在org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:65)〜[spring-session-1.0.1.RELEASE.jar:na]       在org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)〜[tomcat-embed-core-8.0.23.jar:8.0.23]       在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)〜[tomcat-embed-core-8.0.23.jar:8.0.23]       在org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87)〜[spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]       在org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)〜[spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]       在org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)〜[tomcat-embed-core-8.0.23.jar:8.0.23]       在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)〜[tomcat-embed-core-8.0.23.jar:8.0.23]       在org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)〜[spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]       在org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)〜[spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]       在org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)〜[tomcat-embed-core-8.0.23.jar:8.0.23]       在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)〜[tomcat-embed-core-8.0.23.jar:8.0.23]       在org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)〜[spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]       在org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)〜[spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]       在org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)〜[tomcat-embed-core-8.0.23.jar:8.0.23]       在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)〜[tomcat-embed-core-8.0.23.jar:8.0.23]       在org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:69)〜[spring-boot-actuator-1.3.0.M4.jar:1.3.0.M4]       在org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)〜[spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]       在org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)〜[tomcat-embed-core-8.0.23.jar:8.0.23]       在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)〜[tomcat-embed-core-8.0.23.jar:8.0.23]       在org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)~ [tomcat-embed-core-8.0.23.jar:8.0.23]       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)[tomcat-embed-core-8.0.23.jar:8.0.23]       at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)[tomcat-embed-core-8.0.23.jar:8.0.23]       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)[tomcat-embed-core-8.0.23.jar:8.0.23]       at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)[tomcat-embed-core-8.0.23.jar:8.0.23]       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)[tomcat-embed-core-8.0.23.jar:8.0.23]       在org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)[tomcat-embed-core-8.0.23.jar:8.0.23]       在org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)[tomcat-embed-core-8.0.23.jar:8.0.23]       at org.apache.coyote.AbstractProtocol $ AbstractConnectionHandler.process(AbstractProtocol.java:668)[tomcat-embed-core-8.0.23.jar:8.0.23]       at org.apache.tomcat.util.net.NioEndpoint $ SocketProcessor.doRun(NioEndpoint.java:1521)[tomcat-embed-core-8.0.23.jar:8.0.23]       在org.apache.tomcat.util.net.NioEndpoint $ SocketProcessor.run(NioEndpoint.java:1478)[tomcat-embed-core-8.0.23.jar:8.0.23]       在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)[na:1.7.0_67]       at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:615)[na:1.7.0_67]       at org.apache.tomcat.util.threads.TaskThread $ WrappingRunnable.run(TaskThread.java:61)[tomcat-embed-core-8.0.23.jar:8.0.23]       在java.lang.Thread.run(Thread.java:745)[na:1.7.0_67]

我不明白为什么会出现此错误。我将被重定向到失败页面(/ login?error)。

这是我的配置:

@Autowired
private PortalUserDetailsService portalUserDetailsService;

@Autowired
private LoginSuccessHandler loginSuccessHandler;

@Autowired
private LogoutSuccessHandler LogoutSuccessHandler;

@Override
protected void configure(HttpSecurity http) throws Exception {
    // Manage access authority to pages
    http
        .csrf().disable()
        .authorizeRequests()
            .antMatchers("/about").permitAll()
            .anyRequest()
            .fullyAuthenticated().and()
        .httpBasic().and()
        .formLogin()
            .loginPage("/login")
            .permitAll()
            .successHandler(loginSuccessHandler)
            .failureUrl("/login?error" ).and()
        .logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .permitAll()
            .logoutSuccessHandler(LogoutSuccessHandler);
}


@Override
public void configure( WebSecurity web ) throws Exception
{
    // This is here to ensure that the static content (JavaScript, CSS, etc)
    // is accessible without authentication
    web
        .ignoring()
        .antMatchers("/css/**", "/fonts/**", "/img/**", "/js/**", "/webjars/**");
}

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
}

@Bean
public AuthenticationManager authenticationManager() {
    return new ProviderManager(Arrays.asList(activeDirectoryLdapAuthenticationProvider()));
}

@Bean
public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
    ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(domain, ldapUrl);
    provider.setConvertSubErrorCodesToExceptions(true);
    provider.setUseAuthenticationRequestCredentials(true);
    provider.setUserDetailsContextMapper(getUserDetailsContextMapper());
    return provider;
}

private UserDetailsContextMapper getUserDetailsContextMapper() {
    return new UserDetailsContextMapper() {
        @Override
        public UserDetails mapUserFromContext(DirContextOperations dirContextOperations, String s, Collection<? extends GrantedAuthority> collection) {
            PortalUserDetails portalUserDetails = portalUserDetailsService.loadZenithAttributesByUsername(s);
            try {
                portalUserDetails = portalUserDetailsService.addLdapAttributesFromContext(dirContextOperations.getAttributes(), portalUserDetails);
            } catch (NamingException e) {
                e.printStackTrace();
            }
            return portalUserDetails;
        }

        @Override
        public void mapUserToContext(UserDetails userDetails, DirContextAdapter dirContextAdapter) {
        }

    };
}

您是否知道如何解决此错误?

解决方案: 这个问题出现在我的redis配置中。 我改变了这样的配置:

@Primary
@Bean
public RedisTemplate<String,ExpiringSession> redisTemplate2(RedisConnectionFactory connectionFactory) {
    RedisTemplate<String, ExpiringSession> template = new RedisTemplate<String, ExpiringSession>();

    template.setHashValueSerializer(new LdapFailAwareRedisObjectSerializer());

    template.setConnectionFactory(connectionFactory);
    return template;
}

使用此自定义序列化程序:

public class LdapFailAwareRedisObjectSerializer implements RedisSerializer<Object> {

private Converter<Object, byte[]> serializer = new SerializingConverter();
private Converter<byte[], Object> deserializer = new DeserializingConverter();

static final byte[] EMPTY_ARRAY = new byte[0];

public Object deserialize(byte[] bytes) {
    if (isEmpty(bytes)) {
        return null;
    }
    else {
        try {
            return this.deserializer.convert(bytes);
        } catch (Exception ex) {
            throw new SerializationException("Cannot deserialize", ex);
        }
    }
}

public byte[] serialize(Object object) {
    if (object == null) {
        return EMPTY_ARRAY;
    }

    try {
        return serializer.convert(object);
    } catch (Exception ex) {
        return EMPTY_ARRAY;
        //TODO add logic here to only return EMPTY_ARRAY for known conditions
        // else throw the SerializationException
        // throw new SerializationException("Cannot serialize", ex);
    }
}

private boolean isEmpty(byte[] data) {
    return (data == null || data.length == 0);
}
}

1 个答案:

答案 0 :(得分:1)

我有一个类似的problem请看看解决方案。

我需要替换spring-session正在使用的Redis模板,以便我可以查找com.sun.jndi.ldap.LdapCtx对象并阻止spring尝试序列化它。

Mike Kowalski