Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Servlets 如何使jcaptcha与Spring会话一起工作?_Servlets_Captcha_Spring Session_Jcaptcha - Fatal编程技术网

Servlets 如何使jcaptcha与Spring会话一起工作?

Servlets 如何使jcaptcha与Spring会话一起工作?,servlets,captcha,spring-session,jcaptcha,Servlets,Captcha,Spring Session,Jcaptcha,我们实现了由Redis支持的Spring会话,并拥有一个Tomcat服务器集群。当我们通过不设置jvmRoute关闭粘性会话时,我们在jcaptcha服务中不断得到“文本验证失败”。我假设这是因为jcaptchaservlet对springdispatcherservlet一无所知,它拥有所有Spring会话过滤器,因此无法读取会话变量。我们如何使jcaptcha与Spring会话一起工作 以下是我们的设置: Web.xml <servlet> <servlet-nam

我们实现了由Redis支持的Spring会话,并拥有一个Tomcat服务器集群。当我们通过不设置jvmRoute关闭粘性会话时,我们在jcaptcha服务中不断得到“文本验证失败”。我假设这是因为jcaptchaservlet对springdispatcherservlet一无所知,它拥有所有Spring会话过滤器,因此无法读取会话变量。我们如何使jcaptcha与Spring会话一起工作

以下是我们的设置:

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>
redisessionconfig.java

public class CustomHttpSessionAppInitializer extends AbstractHttpSessionApplicationInitializer {}
@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;
    }
}
@配置
@启用RedistpSession
公共类重新会话配置{
@值(${spring.redis.host}”)
私有字符串名称;
@值(${spring.redis.port}”)
私有整数端口;
@值(${spring.redis.database}”)
私有整数数据库;
@值(${spring.redis.password}”)
私有字符串密码;
@值(${spring.server.affinity}”)
私有布尔值isServerAffinity=Boolean.FALSE;
@自动连线
私人SessionIdentifierService SessionIdentifierService;
@豆子
公共绝地连接工厂绝地连接工厂(){
RedisStandaloneConfiguration config=新的RedisStandaloneConfiguration(redisServerName,redisServerPort);
config.setDatabase(redisServerDatabase);
config.setPassword(RedisPassword.of(redisServerPassword));
返回新的JedisConnectionFactory(配置);
}
/*
*我们需要将每个HttpSessionListener注册为一个bean,以便将SessionDestroyeEvent和SessionCreateEvent转换为
*HttpSessionEvent。否则,我们将收到大量关于无法发布会话事件的警告消息。
*请参阅Spring会话文档,网址为:
*{@link}https://docs.spring.io/spring-session/docs/current/reference/html5/#httpsession-httpsessionlistener
*/
@豆子
公共HttpSessionEventPublisher HttpSessionEventPublisher(){
返回新的HttpSessionEventPublisher();
}
@豆子
公共CookieSerializer CookieSerializer(){
DefaultCookieSerializer序列化程序=新的DefaultCookieSerializer();
serializer.setCookieName(“JSESSIONID”);
serializer.setUseBase64编码(false);
if(isServerAffinity){
serializer.setJvmRoute(sessionIdentifierService.getJvmRoute());
}
返回序列化程序;
}
@豆子
公共RedisTemplate RedisTemplate(){
RedisTemplate=新RedisTemplate();
setConnectionFactory(jedisConnectionFactory());
返回模板;
}
}

集成jcaptcha和Spring会话应该不会有问题。只要存在从Redis加载会话的方法(在本例中通过会话cookie),并且会话存在,调用
request.getSession()
request.getSession(false)
将返回Redis支持的会话

这适用于在springSessionRepositoryFilter之后被称为的任何筛选器和servlet。如果查看
SessionRepositoryFilter
的源代码,您将看到
HttpServletRequest
SessionRepositoryRequestWrapper
交换

因此,您的
SimpleImage CaptChaservlet
和用于验证用户响应的任何servlet都将获得一个SessionRepositoryRequestWrapper,它似乎不允许您访问Redis支持的会话

那么问题可能是您的配置;springSessionRepositoryFilter可能未在容器中注册,特别是因为您同时使用web.xml和Servlet 3.0+
WebApplicationInitializer
。如果你的应用程序工作正常,那么你的web.xml很可能工作正常。您是否使用
WebApplicationInitializer
加载web.xml?如果不是,那么可能是您的Java配置没有加载。确保您的web.xml以某种方式加载了您的配置,可能是通过在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>

springSessionRepositoryFilter
org.springframework.web.filter.DelegatingFilterProxy
springSessionRepositoryFilter
/*
要求
错误
查看