Как заставить jcaptcha работать с Spring Session? - PullRequest
0 голосов
/ 05 января 2019

Мы реализовали Spring Session при поддержке Redis и создали кластер серверов Tomcat. Когда мы отключили липкие сессии, не устанавливая jvmRoute, мы продолжаем получать «Проверка текста не удалась» в сервисе jcaptcha. Я предполагаю, что это потому, что сервлет jcaptcha ничего не знает о сервлете Spring Dispatcher, который имеет все фильтры Spring Session и, следовательно, не может прочитать переменную сеанса. Как мы можем заставить jcaptcha работать с Spring Session?

Вот наша установка:

web.xml

<servlet>
    <servlet-name>my-servlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>throwExceptionIfNoHandlerFound</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>my-servlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>jcaptcha</servlet-name>
    <servlet-class>com.octo.captcha.module.servlet.image.SimpleImageCaptchaServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>jcaptcha</servlet-name>
    <url-pattern>/jcaptcha/jcaptcha.jpg</url-pattern>
</servlet-mapping>

CustomHttpSessionAppInitializer.java

public class CustomHttpSessionAppInitializer extends AbstractHttpSessionApplicationInitializer {}

RedisSessionConfig.java

@Configuration
@EnableRedisHttpSession
public class RedisSessionConfig {

    @Value("${spring.redis.host}")
    private String redisServerName;

    @Value("${spring.redis.port}")
    private Integer redisServerPort;

    @Value("${spring.redis.database}")
    private Integer redisServerDatabase;

    @Value("${spring.redis.password}")
    private String redisServerPassword;

    @Value("${spring.server.affinity}")
    private Boolean isServerAffinity = Boolean.FALSE;

    @Autowired
    private SessionIdentifierService sessionIdentifierService;

    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(redisServerName, redisServerPort);
        config.setDatabase(redisServerDatabase);
        config.setPassword(RedisPassword.of(redisServerPassword));
        return new JedisConnectionFactory(config);
    }

    /*
     * We need to register every HttpSessionListener as a bean to translate SessionDestroyedEvent and SessionCreatedEvent into
     * HttpSessionEvent. Otherwise we will got a lot of warning messages about being Unable to publish Events for the session.
     * See Spring Session Docs at:
     * {@link} https://docs.spring.io/spring-session/docs/current/reference/html5/#httpsession-httpsessionlistener
     */
    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }

    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer serializer = new DefaultCookieSerializer();
        serializer.setCookieName("JSESSIONID");
        serializer.setUseBase64Encoding(false);
        if (isServerAffinity) {
            serializer.setJvmRoute(sessionIdentifierService.getJvmRoute());
        }
        return serializer;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(jedisConnectionFactory());
        return template;
    }
}

1 Ответ

0 голосов
/ 08 февраля 2019

Не должно быть проблем при интеграции jcaptcha с Spring Session. Пока существует способ загрузки сеанса из Redis (в данном случае через cookie-файл SESSION) и сеанс существует, вызов request.getSession() или request.getSession(false) вернет сеанс, поддерживаемый Redis.

Это работает в любом фильтре и сервлете, который называется ПОСЛЕ springSessionRepositoryFilter. Если вы посмотрите на исходный код SessionRepositoryFilter, вы увидите, что HttpServletRequest поменялся местами с SessionRepositoryRequestWrapper.

Таким образом, ваш SimpleImageCaptchaServlet и любой сервлет, который вы используете для проверки ответа пользователя, получат SessionRepositoryRequestWrapper, который, по-видимому, даст вам доступ к сеансу с поддержкой Redis.

Тогда проблема может быть в вашей конфигурации; springSessionRepositoryFilter может быть не зарегистрирован в контейнере, тем более что вы используете как web.xml, так и сервлет 3.0+ WebApplicationInitializer. Если ваше приложение работает правильно, то ваш web.xml, скорее всего, работает нормально. Вы используете WebApplicationInitializer для загрузки вашего web.xml? Если нет, то, возможно, ваш Java Config не загружается. Убедитесь, что ваш web.xml каким-то образом загружает вашу конфигурацию, возможно, включив сканирование компонентов (<context:component-scan/>) в файле конфигурации contextLoaderListener xml для загрузки вашей конфигурации Java вместе с:

<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>

для загрузки конфигурации, которая создаст фильтр, который вы затем должны добавить в свой web.xml:

<filter>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

Проверьте ссылку Spring Session на XML config

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...