Исключение, когда многочастная форма POST, прерванная тайм-аутом сеанса, приводит к - PullRequest
3 голосов
/ 26 мая 2011

У нас есть Spring Spring с CAS (я не думаю, что CAS является проблемой).

Проблема НЕ в тайм-ауте сеанса, а в том, как обрабатывается этот тайм-аут.

  1. запросить форму: GET / someform
  2. заполните многочастную форму
  3. перезагрузите сервер или удалите JSESSIONID
  4. отправить форму: POST / someform (с составными данными)

  5. пользователь перенаправлен на экран входа в систему

  6. после входа в систему пользователь перенаправляется на форму: GET / someform
  7. spring пытается повторно опубликовать сохраненную форму (я думаю, что она использует DefaultSavedRequest)
  8. пытается вызвать функцию контроллера, сопоставленную с: POST / someform, но запрос не является составным
  9. мы получаем исключение:

Не удалось вызвать метод-обработчик [общественности 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 Ответ

1 голос
/ 27 мая 2011

Решил проблему, изменив сигнатуру метода контроллера.

Ранее MultipartHttpServletRequest был в сигнатуре метода. Когда весна возвратилась из двустороннего входа в систему, она попыталась вызвать этот метод с обычным 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). SPRING NOW вызывает метод POST с помощью HttpServletRequest, а не MultipartHttpServletRequest. Мы обнаруживаем, что это не MultipartHttpServletRequest и перенаправляем на страницу GET, снова отображая форму для пользователя
...