Spring security Active Directory登录失败时出现支持Hazelcast的Spring会话序列化异常的Spring引导应用程序

Spring security Active Directory登录失败时出现支持Hazelcast的Spring会话序列化异常的Spring引导应用程序,spring-security,spring-boot,hazelcast,spring-ldap,spring-session,Spring Security,Spring Boot,Hazelcast,Spring Ldap,Spring Session,我们有一个使用Hazecast支持的Spring会话的Spring引导应用程序。应用程序使用Spring Security与Active Directory进行身份验证。如果用户尝试使用无效凭据登录,将引发序列化错误: com.hazelcast.nio.serialization.HazelcastSerializationException: java.io.NotSerializableException: com.sun.jndi.ldap.LdapCtx at com.

我们有一个使用Hazecast支持的Spring会话的Spring引导应用程序。应用程序使用Spring Security与Active Directory进行身份验证。如果用户尝试使用无效凭据登录,将引发序列化错误:

com.hazelcast.nio.serialization.HazelcastSerializationException: java.io.NotSerializableException: com.sun.jndi.ldap.LdapCtx
        at com.hazelcast.nio.serialization.SerializationServiceImpl.handleException(SerializationServiceImpl.java:380)
        at com.hazelcast.nio.serialization.SerializationServiceImpl.toData(SerializationServiceImpl.java:235)
        at com.hazelcast.nio.serialization.SerializationServiceImpl.toData(SerializationServiceImpl.java:207)
        at com.hazelcast.map.impl.MapServiceContextImpl.toData(MapServiceContextImpl.java:338)
        at com.hazelcast.map.impl.proxy.MapProxySupport.toData(MapProxySupport.java:1160)
        at com.hazelcast.map.impl.proxy.MapProxyImpl.put(MapProxyImpl.java:96)
        at org.springframework.session.hazelcast.config.annotation.web.http.HazelcastHttpSessionConfiguration$ExpiringSessionMap.put(HazelcastHttpSessionConfiguration.java:112)
        at org.springframework.session.hazelcast.config.annotation.web.http.HazelcastHttpSessionConfiguration$ExpiringSessionMap.put(HazelcastHttpSessionConfiguration.java:102)
        at org.springframework.session.MapSessionRepository.save(MapSessionRepository.java:72)
        at org.springframework.session.MapSessionRepository.save(MapSessionRepository.java:36)
        at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:194)
        at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.access$100(SessionRepositoryFilter.java:170)
        at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:128)
        at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:65)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
        at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:103)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
        at org.apache.coyote.ajp.AbstractAjpProcessor.process(AbstractAjpProcessor.java:868)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1502)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1458)
        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)
这似乎与Redis的另一个问题()相同,但是,在Hazelcast会话映射中,似乎没有类似的机制来控制序列化,而在Spring会话中,Redis有类似的机制

我们已经想出了一个解决方案(如下),但它似乎不太理想,因为
HazelcastHttpSessionConfiguration
似乎并不适合扩展,所以似乎应该有一种我们没有看到的更干净的方式

我们正在扩展HazelcastHttpSessionConfiguration,以在尝试序列化之前,在
ExpiringSessionMap
处删除
LdapCtx
。这似乎并不理想,因为HazelcastHttpSessionConfiguration实际上不支持扩展,需要重复代码

有没有我们缺少的更好的解决方案

@配置
公共类CustomHazelCastHttpSessionConfiguration扩展了HazelcastHttpSessionConfiguration{
私有字符串sessionmaname=“spring:session:sessions”;
private int maxInactiveIntervalInSeconds=1800;
@豆子
公共会话存储库会话存储库(
HazelcastInstance(HazelcastInstance,SessionEntryListener sessionListener){
sessionRepository(hazelcastance、sessionListener);
MapSessionRepository sessionRepository=新建MapSessionRepository(
新的CustomExpiringSessionMap(hazelcastInstance.getMap(this.sessionMapName));
会话存储库
.setDefaultMaxInactiveInterval(此.maxInactiveIntervalInSeconds);
返回会话存储库;
}
@凌驾
public void setSessionMapName(字符串sessionMapName){
this.sessionmaName=sessionmaName;
super.setSessionMapName(sessionMapName);
}
@凌驾
public void setMaxInactiveIntervalInSeconds(int maxInactiveIntervalInSeconds){
this.maxInactiveIntervalInSeconds=maxInactiveIntervalInSeconds;
super.setMaxInactiveIntervalInSeconds(maxInactiveIntervalInSeconds);
}
静态类CustomExpiringSessionMap实现映射{
私人IMap代表;
CustomExpiringSessionMap(IMap委托){
this.delegate=委托;
}
公共ExpiringSession put(字符串键,ExpiringSession值){
如果(值==null){
返回this.delegate.put(键,值);
}
for(字符串attrName:value.getAttributeNames()){
对象attrVal=value.getAttribute(attrName);
//不要在BadCredentialsException中序列化LdapCtx
if(BadCredentialsException的属性值实例)&&
((BadCredentialsException)attrVal.getCause()!=null&&
((BadCredentialsException)attrVal.getCause()实例的ActiveDirectoryAuthenticationException&&
((BadCredentialsException)attrVal.getCause().getCause()!=null&&
((BadCredentialsException)attrVal.getCause().getCause()实例javax.naming.AuthenticationException){
((javax.naming.AuthenticationException)((BadCredentialsException)attrVal.getCause().getCause()).setResolvedObj(null);
}
}
返回此.delegate.put(键、值、值.getMaxInactiveIntervalInSeconds(),
时间单位(秒);
}
/*…复制并粘贴ExpiringSessionMap的其余部分*/
}
}

更清洁的解决方案是
瞬态属性

如果您有一个web筛选器,则可以向其传递一个属性列表以控制行为,而这是一个以逗号分隔的属性名称列表,以从序列化中排除


如果您需要更多信息,请告诉我。

更干净的解决方案是
瞬态属性

如果您有一个web筛选器,则可以向其传递一个属性列表以控制行为,而这是一个以逗号分隔的属性名称列表,以从序列化中排除

如果您需要更多信息,请与我联系。

您应该为遇到问题的对象配置一个

这样,您就可以解决Hazelcast配置中的问题,而无需扩展/复制Spring会话的Hazelcast配置。

您应该为遇到问题的对象配置


这样,您就可以解决Hazelcast配置中的问题,而无需扩展/复制Spring会话的Hazelcast配置。

谢谢,这让事情变得更干净了。我们为ExpiringSession实现了一个自定义序列化程序,因为它是被序列化的根对象,最终简化了一些事情。谢谢,这让事情变得更干净了。我们为ExpiringSession实现了一个自定义序列化程序,因为它是被序列化的根对象,最终简化了一些事情。