Hazecastを使用したSpringセッションを使用するSpringブートアプリケーションがあります。アプリケーションは、Spring Securityを使用してActive Directoryで認証します。ユーザーが無効な資格情報を使用してログインしようとすると、シリアル化のエラーがスローされます。これは、Redisのと別の問題(Spring Boot with Session/Redis Serialization Error with Bad Active Directory Ldap Credentials)と同じように見えるHazelcastを使用したSpringブートアプリケーションActive Directoryログイン失敗のバックエンドSpringセッションのシリアライゼーション例外
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)
、しかし、同様のメカニズムがあるように表示されません。 SpringセッションのRedisのためのHazelcastセッションマッピングの直列化を制御します。
HazelcastHttpSessionConfiguration
は実際には拡張に適していないようで、理想的ではないように思われます。したがって、私たちがそうでないようなクリーンな方法があるようです見て。
ExpiringSessionMap
になるようにHazelcastHttpSessionConfiguration
を拡張して、LdapCtx
を削除してからシリアル化を試みます。これは、HazelcastHttpSessionConfiguration
がコードの重複を必要とするので、実際には拡張に自己貸与するものではないため、理想的ではないようです。
解決方法はありますか?
@Configuration
public class CustomHazelcastHttpSessionMapConfiguration extends HazelcastHttpSessionConfiguration{
private String sessionMapName = "spring:session:sessions";
private int maxInactiveIntervalInSeconds = 1800;
@Bean
public SessionRepository<ExpiringSession> sessionRepository(
HazelcastInstance hazelcastInstance, SessionEntryListener sessionListener) {
super.sessionRepository(hazelcastInstance, sessionListener);
MapSessionRepository sessionRepository = new MapSessionRepository(
new CustomExpiringSessionMap(hazelcastInstance.getMap(this.sessionMapName)));
sessionRepository
.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
return sessionRepository;
}
@Override
public void setSessionMapName(String sessionMapName) {
this.sessionMapName = sessionMapName;
super.setSessionMapName(sessionMapName);
}
@Override
public void setMaxInactiveIntervalInSeconds(int maxInactiveIntervalInSeconds) {
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
super.setMaxInactiveIntervalInSeconds(maxInactiveIntervalInSeconds);
}
static class CustomExpiringSessionMap implements Map<String, ExpiringSession> {
private IMap<String, ExpiringSession> delegate;
CustomExpiringSessionMap(IMap<String, ExpiringSession> delegate) {
this.delegate = delegate;
}
public ExpiringSession put(String key, ExpiringSession value) {
if (value == null) {
return this.delegate.put(key, value);
}
for (String attrName : value.getAttributeNames()) {
Object attrVal = value.getAttribute(attrName);
// Don't serialize LdapCtx in a BadCredentialsException
if (attrVal instanceof BadCredentialsException &&
((BadCredentialsException) attrVal).getCause() != null &&
((BadCredentialsException) attrVal).getCause() instanceof ActiveDirectoryAuthenticationException &&
((BadCredentialsException) attrVal).getCause().getCause() != null &&
((BadCredentialsException) attrVal).getCause().getCause() instanceof javax.naming.AuthenticationException) {
((javax.naming.AuthenticationException) ((BadCredentialsException) attrVal).getCause().getCause()).setResolvedObj(null);
}
}
return this.delegate.put(key, value, value.getMaxInactiveIntervalInSeconds(),
TimeUnit.SECONDS);
}
/*... copy and paste of the rest of ExpiringSessionMap */
}
}
ありがとうございました。これはかなりクリーンなものでした。 ExpiringSessionのカスタムシリアライザは、シリアライズされているルートオブジェクトで実装されており、シンプルなものになります。 –