问题描述
||
我们的CAS具有Spring安全性(我认为CAS不是问题所在)。
问题不在于会话超时,而在于如何处理该超时。
索取表格:GET / someform
填写多部分表格
重新启动服务器,或删除JSESSIONID
提交表单:POST / someform(包含多部分数据)
用户被重定向到登录屏幕
登录用户重定向到以下形式后:GET / someform
spring尝试重新发布已保存的表单(我认为它使用的是DefaultSavedRequest)
它尝试调用映射到以下位置的控制器功能:POST / someform,但请求不是多部分的
我们得到一个例外:
未能调用处理程序方法
[上市
org.springframework.web.servlet.ModelAndView
com.xxx.xxx.XXXController.xxxPost(org.springframework.web.multipart.MultipartHttpServletRequest)];
嵌套异常为
java.lang.IllegalStateException:
当前请求不是类型
org.springframework.web.multipart.MultipartHttpServletRequest:
com.secondmarket.web.UrlLowerCaseFilter$LowerCaseUrlServletRequestWrapper@77fb58b6
这是在AccessDeniedException上将请求保存到会话的代码,它位于HttpSessionRequestCache(由ExceptionTranslationFilter调用)中:
public void saveRequest(HttpServletRequest request,HttpServletResponse response) {
if (!justUseSavedRequestOnGet || \"GET\".equals(request.getMethod())) {
DefaultSavedRequest savedRequest = new DefaultSavedRequest(request,portResolver);
if (createSessionAllowed || request.getSession(false) != null) {
// Store the HTTP request itself. Used by AbstractAuthenticationProcessingFilter
// for redirection after successful authentication (SEC-29)
request.getSession().setAttribute(WebAttributes.SAVED_REQUEST,savedRequest);
logger.debug(\"DefaultSavedRequest added to Session: \" + savedRequest);
}
}
}
如果它是一个多部分请求,我如何owverwrite HttpSessionRequestCache或ExceptionTranslationFilter不保存该请求?
解决方法
通过修改控制器方法签名解决了该问题。
以前,MultipartHttpServletRequest位于方法签名中。当Spring从登录往返中回来时,它尝试使用常规HttpServletRequest调用此方法,但失败了。
@RequestMapping(value = \"/xxx\",method = RequestMethod.POST)
public ModelAndView doAmlCheckPost(MultipartHttpServletRequest req) {
UserInfo currentUserInfo = UserInfo.getCurrentUserInfo(req);
MultipartFile someFile = req.getFile(\"someFile\");
解决方法是使用常规的RequestMapping,然后从URL中提取文件。如果request不是MultipartHttpServletRequest的instance-重定向到GET方法,它将重新显示表单
@RequestMapping(value = \"/xxx\",method = RequestMethod.POST)
public ModelAndView doAmlCheckMultipartPost(HttpServletRequest req,@RequestParam(value = \"someFile\",required = false) MultipartFile someFile) {
if(!(req instanceof MultipartHttpServletRequest)){
return \"redirect:/xxx\";
}
现在的流程如下:
索取表格:GET / someform
填写多部分表格
重新启动服务器,或删除JSESSIONID
提交表单:POST / someform(包含多部分数据)在会话中保存了发生的请求,但是没有办法保存多部分数据,它是二进制的,无法序列化
用户被重定向到登录屏幕
登录用户重定向到以下形式后:GET / someform
Spring尝试重新发布已保存的表单(我认为它使用的是DefaultSavedRequest)现在使用HttpServletRequest而不是MultipartHttpServletRequest调用POST方法。我们检测到它不是MultipartHttpServletRequest,然后重定向到GET页面,向用户重新显示表单