Tomcat 7聚类 - 会话复制与Spring Boot和Spring Security不起作用



我在我们的tomcat会话复制配置方面有问题。

在我们的公司,我们正在使用Tomcat 7 Servlet容器Apache HTTPD 2.4.6配置用于使用MOD_JK/TOMCAT-CONNECTORS 1.2.37(在CentOS 7 x64上运行)的负载平衡。会话复制正在与Tomcat Manager合作,这意味着如果我们登录到HTML Manager后杀死了其中一个Tomcats,我们不需要再次登录(我们将其设置为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相似,.77和.79 ip adresses被切换(当然更改了唯一的IP)。

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
        }
    }
}

任何帮助将不胜感激。

似乎我终于解决了它。集群中的一台机器正在运行以前的Tomcat版本。在将其从v7.0.54升级到v7.0.69(也更新Java)之后,一切正常。

最新更新