Servlets 如何使jcaptcha与Spring会话一起工作?
我们实现了由Redis支持的Spring会话,并拥有一个Tomcat服务器集群。当我们通过不设置jvmRoute关闭粘性会话时,我们在jcaptcha服务中不断得到“文本验证失败”。我假设这是因为jcaptchaservlet对springdispatcherservlet一无所知,它拥有所有Spring会话过滤器,因此无法读取会话变量。我们如何使jcaptcha与Spring会话一起工作 以下是我们的设置: Web.xmlServlets 如何使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
<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
/*
要求
错误
查看