0

我有關於我們的Tomcat會話複製配置的問題。Tomcat 7集羣 - 會話複製不適用於彈簧引導和彈簧安全

在我們公司,我們使用Apache HTTPD 2.4.6後面的Tomcat 7 servlet容器,配置爲使用mod_jk/tomcat-connectors 1.2.37(在CentOS 7 x64上運行)進行負載平衡。會話複製與Tomcat管理器一起工作,這意味着如果我們在登錄到HTML管理器後終止一個Tomcat,我們不需要再次登錄(我們已經在web.xml中將其設置爲<distributable />。看到服務器被成功發現彼此從catalina.log:

2017.10.06 09:25:15 [INFO] org.apache.catalina.ha.tcp.SimpleTcpCluster memberAdded: Replication member added:org.apache.catalina.tribes.membership.StaticMember[tcp://10.35.217.77:4444,10.35.217.77,4444, alive=0, securePort=-1, UDP Port=-1, id={1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 }, payload={}, command={}, domain={100 101 108 116 97 45 115 116 97 ...(12)}, ] 
2017.10.06 09:25:15 [INFO] org.apache.catalina.tribes.group.interceptors.TcpFailureDetector performBasicCheck: Suspect member, confirmed alive.[org.apache.catalina.tribes.membership.StaticMember[tcp://10.35.217.77:4444,10.35.217.77,4444, alive=0, securePort=-1, UDP Port=-1, id={1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 }, payload={}, command={}, domain={100 101 108 116 97 45 115 116 97 ...(12)}, ]] 

然而,當我們部署一個示例春季啓動應用程序,並殺死其中我們認證的用戶Tomcat的,在登錄提示再次出現我們。一直在試圖解決這個問題很長時間,這讓我們瘋狂,我們缺少什麼?配置如下:

Tomcat/context.xml:

<Context> 
    <WatchedResource>WEB-INF/web.xml</WatchedResource> 
    <Manager className="org.apache.catalina.ha.session.DeltaManager" 
     expireSessionsOnShutdown="false" 
     notifyListenersOnReplication="true" /> 
    <ResourceLink name="jdbc/postgres" global="jdbc/postgres" 
     type="javax.sql.DataSource" /> 
</Context> 

的Tomcat/server.xml中:

<Server port="8005" shutdown="SHUTDOWN" address="10.35.217.77"> 
    <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> 
    <Listener className="org.apache.catalina.core.JasperListener" /> 
    <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> 
    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> 
    <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> 
    <GlobalNamingResources> 
     <Resource name="UserDatabase" auth="Container" 
      type="org.apache.catalina.UserDatabase" 
      description="User database that can be updated and saved" 
      factory="org.apache.catalina.users.MemoryUserDatabaseFactory" 
      pathname="conf/tomcat-users.xml" /> 
     <Resource name="jdbc/postgres" auth="Container" type="javax.sql.DataSource" 
      username="postgres" password="" 
      url="jdbc:postgresql://127.0.0.1:5432/postgres" 
      driverClassName="org.postgresql.Driver" 
      initialSize="5" maxWait="5000" 
      maxActive="120" maxIdle="5" 
      validationQuery="select 1" 
      poolPreparedStatements="true". 
      factory="org.apache.commons.dbcp.BasicDataSourceFactory" /> 
    </GlobalNamingResources> 
    <Service name="Catalina"> 
     <Connector address="0.0.0.0" port="8080" protocol="HTTP/1.1" 
      connectionTimeout="30000" redirectPort="8443" 
      enableLookups="false" maxPostSize="20000" 
      executor="tcThreadPool" /> 
     <Connector address="10.35.217.77" port="8009" protocol="AJP/1.3" 
      redirectPort="8443" /> 
     <Engine name="Catalina" defaultHost="cluster" jvmRoute="node1"> 
      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" 
       channelSendOptions="6" channelStartOptions="3"> 
       <Channel className="org.apache.catalina.tribes.group.GroupChannel"> 
        <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" 
         autoBind="9" selectorTimeout="5000" maxThreads="6" 
         address="10.35.217.77" port="4444" /> 
        <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> 
         <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender" /> 
        </Sender> 
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpPingInterceptor" /> 
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector" /> 
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor" /> 
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.StaticMembershipInterceptor"> 
         <Member className="org.apache.catalina.tribes.membership.StaticMember" securePort="-1" 
          host="10.35.217.79" port="4444" domain="delta-static" 
          uniqueId="{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}" /> 
        </Interceptor> 
       </Channel> 
       <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=".*\.gif;.*\.jpg;.*\.png;.*\.css" /> 
       <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve" /> 
       <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener" /> 
       <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener" /> 
      </Cluster> 
      <Realm className="org.apache.catalina.realm.LockOutRealm"> 
       <Realm className="org.apache.catalina.realm.UserDatabaseRealm" 
        resourceName="UserDatabase"/> 
      </Realm> 
      <Host name="cluster" appBase="webapps" 
       unpackWARs="true" autoDeploy="true"> 
       <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" 
        prefix="localhost_access_log." suffix="log" rotatable="false" 
        pattern="%h %l %u %t &quot;%r&quot; %s %b" /> 
      </Host> 
     </Engine> 
    </Service> 
</Server> 

另一server.xml中是相似的,與0.77和0.79的IP不會忽略被切換(當然的UniqueID被改變)。

SpringBootApp/WebSecurityConfig.java

@Configuration 
@EnableWebSecurity 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 
    private static final Logger logger = Logger.getLogger(WebSecurityConfig.class.getName()); 

    @Bean 
    public UserDetailsContextMapperImpl contextMapper() { 
     return new UserDetailsContextMapperImpl(); 
    } 

    @Autowired 
    PreferenceDao preferenceDao; 

    @Bean 
    public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() { 
     ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(
       preferenceDao.findByKey("ldap.domain").getValue(), 
       preferenceDao.findByKey("ldap.host").getValue() 
     ); 
     logger.info("Connected to LDAP."); 
     provider.setConvertSubErrorCodesToExceptions(true); 
     provider.setUseAuthenticationRequestCredentials(true); 
     provider.setSearchFilter("(sAMAccountName={0})"); 
     provider.setUserDetailsContextMapper(contextMapper()); 
     return provider; 
    } 

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.inMemoryAuthentication() 
     .withUser("user") 
     .password("s3cr3t") 
     .roles("USER"); 
    } 
    protected void configure(HttpSecurity http) throws Exception { 
     http. 
       authorizeRequests() 
       .antMatchers("/css/**", "/js/**", "/img/**", "/font/**", "/", "/login?logout").permitAll() 
       .anyRequest().hasAuthority("ROLE_USER") 
       .and() 
       .formLogin().loginPage("/login").permitAll() 
       .and() 
       .logout().logoutSuccessUrl("/login?logout").permitAll(); 
    } 

    protected class UserDetailsContextMapperImpl implements UserDetailsContextMapper, Serializable { 
     @Override 
     public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) { 
      List<GrantedAuthority> mappedAuthorities = new ArrayList<>(); 
      mappedAuthorities.add(new SimpleGrantedAuthority("ROLE_USER")); 
      return new User(username, "", true, true, true, true, mappedAuthorities); 
     } 

     @Override 
     public void mapUserToContext(UserDetails user, DirContextAdapter ctx) { 
      //do nothing 
     } 
    } 
} 

任何幫助將不勝感激。

+0

你可能在你自己的問題中有答案。你的應用程序是否標記爲「'?看看這個答案https://stackoverflow.com/a/372​​72352/4190848 – jlumietu

+0

感謝您的快速回復。是的,我已經把完全相同的web.xml放在Spring Boot應用程序中。還用包含distributable =「true」屬性的context.xml來試用它。 – Rekviem

+0

您確定會話中保存的所有數據都是可序列化的嗎?只有一個會話參數不可序列化,整個會話將不會在集羣中複製 – jlumietu

回答

0

好像我終於解決了它。集羣中的一臺機器運行的是Tomcat的早期版本。在將它從v7.0.54升級到v7.0.69(同時更新java)之後,一切正常。