开发者

Exception when multipart form POST interrupted by session timeout results in an

We have Spring security with CAS (I don't think CAS is the problem).

The problem is NOT the session timeout, rather how this timeout is handled.

  1. request a form: GET /someform
  2. fill out a multipart form
  3. restart the server, or delete JSESSIONID
  4. submit the form: POST /someform (with multipart data)

  5. user is redirected to the login screen

  6. after login user is redirected to the form: GET /someform
  7. spring tries to re-post the saved form (I think it's using DefaultSavedRequest)
  8. it tries to call the controller function mapped to: POST /someform, but the request is not multipart
  9. we get an exception:

Failed to invoke handler method [public org.springframework.web.servlet.ModelAndView com.xxx.xxx.XXXController.xxxPost(org.springframework.web.multipart.MultipartHttpServletRequest)]; nested exception is java.lang.IllegalStateException: Current request is not of type org.springframework.web.multipart.MultipartHttpServletRequest: com.secondmarket.web.UrlLowerCaseFilter$LowerCaseUrlServletRequestWrapper@77fb58b6

This is the code that saves the request to the session upon AccessDeniedException, it's in HttpSessionRequestCache (called by 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 H开发者_如何学PythonTTP 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);
        }
    }

}

How can i owverwrite HttpSessionRequestCache or ExceptionTranslationFilter to NOT save the request if it's a multipart request?


Solved the problem by modifying controller method signature.

Previously, MultipartHttpServletRequest was in the method signature. When spring came back from login round trip, it tried calling this method with regular HttpServletRequest, and failed.

@RequestMapping(value = "/xxx", method = RequestMethod.POST)
public ModelAndView doAmlCheckPost(MultipartHttpServletRequest req) {
    UserInfo currentUserInfo = UserInfo.getCurrentUserInfo(req);

    MultipartFile someFile = req.getFile("someFile");

The fix is to use regular RequestMapping, and pick up the files from the URL. If request is not instanceof MultipartHttpServletRequest - redirect to the GET method, which redisplays the form

@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";
    }

So the flow is now as follows:

  1. request a form: GET /someform
  2. fill out a multipart form
  3. restart the server, or delete JSESSIONID
  4. submit the form: POST /someform (with multipart data) WHAT HAPPENS HERE IS REQUEST IS SAVED IN THE SESSION, BUT THERE IS NO WAY TO SAVE MULTIPART DATA, IT'S BINARY AND CANNOT BE SERIALIZED
  5. user is redirected to the login screen
  6. after login user is redirected to the form: GET /someform
  7. spring tries to re-post the saved form (I think it's using DefaultSavedRequest) SPRING NOW CALLS THE POST METHOD WITH HttpServletRequest, not MultipartHttpServletRequest. We detect that it's not MultipartHttpServletRequest and redirect to the GET page, redisplaying the form to the user
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜