多部分表单POST被会话超时中断导致的异常导致

时间:2011-05-26 15:02:06

标签: java spring spring-security session-timeout multipartform-data

我们有CAS的Spring安全性(我不认为CAS是问题)。

问题不是会话超时,而是如何处理此超时。

  1. 申请表格:GET / someform
  2. 填写多部分表格
  3. 重启服务器,或删除JSESSIONID
  4. 提交表单:POST / someform(包含多部分数据)

  5. 用户被重定向到登录屏幕

  6. 登录后,用户被重定向到表格:GET / someform
  7. spring尝试重新发布已保存的表单(我认为它使用的是DefaultSavedRequest)
  8. 它尝试调用映射到的控制器函数:POST / someform,但请求不是multipart
  9. 我们得到一个例外:
  10.   

    无法调用处理程序方法   [上市   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);
            }
        }
    
    }
    

    如果请求是多部分请求,我怎么能写HttpSessionRequestCache或ExceptionTranslationFilter来保存请求?

1 个答案:

答案 0 :(得分:1)

通过修改控制器方法签名解决了这个问题。

以前,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中获取文件。如果请求不是MultipartHttpServletRequest的实例 - 重定向到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";
    }

现在流程如下:

  1. 申请表格:GET / someform
  2. 填写多部分表格
  3. 重启服务器,或删除JSESSIONID
  4. 提交表格:POST / someform(包含多部分数据)会议中保存的请求是在会议中保存的,但是没有办法保存多个数据,这是二进制且无法串行化
  5. 用户被重定向到登录屏幕
  6. 登录后,用户被重定向到表格:GET / someform
  7. spring尝试重新发布保存的表单(我认为它使用DefaultSavedRequest)现在使用HttpServletRequest调用POST方法,而不是使用MultipartHttpServletRequest。我们检测到它不是MultipartHttpServletRequest并重定向到GET页面,将表单重新显示给用户