Spring,Struts2,Shiro中使用google验证码Kaptcha 获取不到session中验证码的解决方法

阅读更多

Spring,Struts2,Shiro中使用google验证码Kaptcha 获取不到session中验证码的解决方法

 

Kaptcha验证码的原理:

 

前台请求一个图片,该图片src属性指向的url其实是在web.xml中配置的一个servlet,该servlet由Kaptcha提供,

 

就是随机生成一串字符,然后存入session中,再将字符转成图片传到前台.

 

验证时,前台输入验证码传到后台,后台从session中取出原始的验证码跟前台传过来的比对,

 

看看是否一致.

 

使用Spring,Struts2,Shiro这三个框架后,发现验证码的session老是为null.

 

其中,Shiro的session配置的是org.apache.shiro.web.session.mgt.DefaultWebSessionManager

这个SessionManager完全取代了容器中的Session管理器.

 

分析一下,验证码产生的流程:

(1) 前台请求验证码

(2) 后台收到请求,创建session,然后将验证码装入Session中

 

验证流程

用户点击登录按钮,发送一个ajax请求到后台,后台负责处理请求的Action试图从Session中取出原始验证码.

 

问题就出在取原始验证码的步骤中,取出的是null.

 

分析原因: 验证码产生时的Session可能和ajax登录请求的Session不是一个Session,导致取不到原始验证码.

 

写了个Session的监听器发现确实在发送ajax登录请求时生成了一个新的session和获取验证码时的Session不同.

 

网上搜索发现:

 

"在用Struts的时候发现这样一个问题,不管我们的程序中是否创建了一个新的session,从页面提交表单到action类,

再跳转到页面的时候url中总是出现了;jsessionid这样的一长串内容,这是由于新建的session导致容器产生的。

 

经过深入研究struts的代码发现问题所在,原来是struts在处理自动Locale时导致的,struts调用了request.getSession()方法,

该方法等同于 request.getSession(true) ,相当于不存在session时就自动创建一个新的session,于是就出现前面提到的现象。

 

要解决这个问题必须关闭struts的自动Locale的功能,不过很简单,只用在struts-config.xml的controller配置增加一个locale参数值等于false即可,"

 

问题的原因估计是struts2重新生成了一个Session.

 

结合看了下web.xml中struts的过滤器配置和shiro的过滤器配置,发现,struts的过滤器在shiro的过滤器前面.

 

这样在发送获取验证码的请求时,请求先被struts的过滤器拦截,struts发现Session不存在,就先产生了一个Session(A),并且验证码也是存储在这个Session(A)中的.

 

紧接着shiro的过滤器因为使用了自己的SessionManager,貌似不能使用前面struts已经创建的Session(A),于是又创建了一个Session(B)(这里纯推测),

 

导致Session变化了.

 

然后,再次调用ajax登录请求准备检查验证码是否正确.这是,其实还是struts先拦截了请求,但是发现已经有Session(B)了(是前面shiro创建的)(貌似struts能使用shiro创建的Session?)

 

这样struts是用了这个Session(B),而验证码是存在Session(A)中的.

 

解决的办法:

 

没有通过网上搜到的修改struts-config.xml的controller配置的(因为不知道在神马地方修改)

 

只需要在web.xml中将shiro的过滤器配置放到struts的过滤器配置前面.

 

切记, 用到shiro框架最好把该框架需要在web.xml中配置的过滤器配置成 第一个 过滤器.

 

你可能感兴趣的:(Spring,Struts2,Shiro,验证码,获取不到)