Проблема с Spring Security, Spring Webflow, загрузкой файлов и UTF-8

У меня есть проблема, очень похожая на описанную здесь: загрузка файла с использованием Spring WebFlow 2.4.0, параметр не связан, но в нем ничего не упоминалось о проблемах UTF-8. Я использую Spring Framework 4.1.6, Spring Security 4.0.2 и Spring Webflow 2.4.2.

Вращается вокруг StandardServletMultipartResolver против CommonsMultipartResolver насколько я могу судить, но я не уверен. Если я использую CommonsMultipartResolver Я могу загружать файлы на любую страницу, за исключением страниц Webflow и кодировки UTF-8, которая работает также на всех страницах. Однако на страницах Webflow выдается исключение при попытке доступа к файлу. Если я использую StandardServletMultipartResolver тогда все загружаемые файлы работают, включая Webflow, но на любой странице, которая имеет символ UTF-8, например, caractère, я получаю мусор.

Самое странное, что я вижу в FireBug, что файл публикуется, когда я использую решатель общих ресурсов. Кроме того, если я отлаживаю RequestContext Исходя из Webflow, я также вижу файл, скрытый на 4 уровня в запросах. Код для общего распознавателя (стандартный код распознавателя см. В конце публикации):

public FileResult uploadFile(Recipe recipe, RequestContext requestContext) {
    ServletExternalContext context = (ServletExternalContext) requestContext.getExternalContext();
    MultipartHttpServletRequest multipartRequest = new DefaultMultipartHttpServletRequest((HttpServletRequest)context.getNativeRequest());
    MultipartFile file = multipartRequest.getFile("file");

Итак, это проблема Spring Security или Spring Webflow? Я подозреваю, что распознаватель общих ресурсов сработал бы, если бы я мог правильно привести приведенный выше RequestContext, но я пробовал множество комбинаций без удачи. Любое руководство по этому вопросу будет принята с благодарностью.

Вот некоторые соответствующие конфигурации и код:

WebMvcConfig

@Bean
public CommonsMultipartResolver filterMultipartResolver() {
    CommonsMultipartResolver resolver = new CommonsMultipartResolver();
    resolver.setDefaultEncoding("UTF-8");
    return resolver;
}

SecurityConfig

@Override
protected void configure(HttpSecurity http) throws Exception {
    CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
    characterEncodingFilter.setEncoding("UTF-8");
    characterEncodingFilter.setForceEncoding(true);

    http
    //.csrf().disable()
    .addFilterBefore(characterEncodingFilter, CsrfFilter.class)
    ...more settings...

SecurityInitializer

@Override
protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
    insertFilters(servletContext, new MultipartFilter());
}

Действие веб-потока

<action-state id="uploadFile">
    <evaluate expression="fileActions.uploadFile(recipe, flowRequestContext)"/>
    <transition to="review"/>
</action-state>

Метод загрузки файла

public FileResult uploadFile(Recipe recipe, RequestContext requestContext) {
    ServletExternalContext context = (ServletExternalContext) requestContext.getExternalContext();
    MultipartHttpServletRequest multipartRequest = new StandardMultipartHttpServletRequest((HttpServletRequest)context.getNativeRequest());
    MultipartFile file = multipartRequest.getFile("file");
    ...rest of code to save the file...

1 ответ

Решение

Оказывается, вы можете разыграть RequestContext, чтобы получить MultipartHttpServletRequest но это не красиво Вот чем я закончил:

Метод загрузки файла

public FileResult uploadFile(Recipe recipe, RequestContext requestContext) {
    logger.debug("uploadFile");

    ServletExternalContext context = (ServletExternalContext) requestContext.getExternalContext();
    SecurityContextHolderAwareRequestWrapper wrapper1 = (SecurityContextHolderAwareRequestWrapper)context.getNativeRequest();
    HttpServletRequestWrapper wrapper2 = (HttpServletRequestWrapper)wrapper1.getRequest();
    FirewalledRequest firewall = (FirewalledRequest)wrapper2.getRequest();
    MultipartHttpServletRequest multipartRequest = (DefaultMultipartHttpServletRequest)firewall.getRequest();
    MultipartFile file = multipartRequest.getFile("file");
    ...rest of code to save the file...

Используя это, я могу сохранить CommonsMultipartResolverВсе загрузки файлов в приложении работают независимо от того, есть ли у вас Webflow или нет, и у меня нет проблем с UTF-8 и искалечением символов.

Я не особенно доволен этим решением (даже если оно работает), поскольку оно зависит от конкретной вложенности запросов, которые могут измениться в будущем (?). Мне было бы интересно, сталкивался ли кто-нибудь еще с той же проблемой UTF-8 и как они решили ее, но сейчас я собираюсь проверить это и двигаться дальше.

Другие вопросы по тегам