Java 上传文件返回403错误-Spring MVC

Java 上传文件返回403错误-Spring MVC,java,spring,spring-mvc,spring-security,Java,Spring,Spring Mvc,Spring Security,在我的SpringMVC项目中,我试图通过一个简单的表单上传一个文件 HTML格式: <form method="POST" enctype="multipart/form-data" action="/upload"> <label>Select File</label> <input type="file" name="file"/> </form> 安全配置: @Configuration @EnableWeb

在我的SpringMVC项目中,我试图通过一个简单的表单上传一个文件

HTML格式:

<form method="POST" enctype="multipart/form-data" action="/upload">
    <label>Select File</label> 
    <input type="file" name="file"/>
</form>
安全配置:

@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/upload").permitAll()
            .and()
               .exceptionHandling().accessDeniedPage("/403")
    }
}
然而,我得到了一个
403:Forbidden
错误,并且每次都被重定向到我的403.html视图

到目前为止,我已经尝试在单独的类中初始化Spring安全过滤器之前指定
MultipartFilter
,但没有成功

public class SecurityApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

    @Override
    protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
        insertFilters(servletContext, new MultipartFilter());
    }
}
有什么想法吗

更新:包括我的WebAppInitializer

@Configuration
@Import({ WebSecurityConfig.class })
public class WebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        System.out.println(":::Starting My App:::");
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(WebMVCConfig.class);
        context.setServletContext(servletContext);
        context.setConfigLocation("com.myApp.configuration");
    }

}
我有一个servlet请求属性列表,返回以下403错误:

javax.servlet.forward.request_uri
javax.servlet.forward.context_path
javax.servlet.forward.servlet_path
__spring_security_scpf_applied
org.springframework.web.servlet.DispatcherServlet.THEME_SOURCE
SPRING_SECURITY_403_EXCEPTION
org.springframework.web.servlet.DispatcherServlet.THEME_RESOLVER
springMacroRequestContext
themes
thymeleafEvaluationContext
org.springframework.security.web.FilterChainProxy.APPLIED
_csrf
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.FILTERED
org.springframework.security.web.csrf.CsrfFilter@539743f9.FILTERED
beans
springRequestContext
org.springframework.web.servlet.HandlerMapping.introspectTypeLevelMapping
org.springframework.web.servlet.DispatcherServlet.FLASH_MAP_MANAGER
org.springframework.web.servlet.DispatcherServlet.CONTEXT
org.springframework.core.convert.ConversionService
execInfo
org.springframework.web.servlet.HandlerMapping.pathWithinHandlerMapping
org.springframework.web.context.request.async.WebAsyncManager.WEB_ASYNC_MANAGER
org.springframework.web.servlet.resource.ResourceUrlProvider
org.springframework.web.servlet.DispatcherServlet.OUTPUT_FLASH_MAP
org.springframework.web.servlet.HandlerMapping.bestMatchingPattern
org.springframework.security.web.csrf.CsrfToken
org.springframework.web.servlet.DispatcherServlet.LOCALE_RESOLVER
更新#2:这肯定是一个CSRF问题;当我在我的
WebSecurityConfig
中包含以下内容时,我没有得到
403

.csrf().disable()
这将在Spring安全参考的一节中介绍。您有两个选择:

在Spring Security之前放置MultipartFilter

第一个选项是确保在Spring安全过滤器之前指定MultipartFilter。在Spring安全过滤器之前指定MultipartFilter意味着没有调用MultipartFilter的授权,这意味着任何人都可以在服务器上放置临时文件。但是,只有授权用户才能提交由应用程序处理的文件。一般来说,这是推荐的方法,因为临时文件上载对大多数服务器的影响是可以忽略的

为了确保在使用java配置的Spring安全筛选器之前指定MultipartFilter,用户可以覆盖beforeSpringSecurityFilterChain,如下所示:

公共类SecurityApplicationInitializer扩展了AbstractSecurityWebApplicationInitializer{
@凌驾
受保护的SpringSecurityFilterChain之前的void(ServletContext ServletContext){
insertFilters(servletContext,新的MultipartFilter());
}
}
要确保在使用XML配置的Spring安全筛选器之前指定MultipartFilter,用户可以确保将MultipartFilter的元素放置在web.XML中springSecurityFilterChain之前,如下所示:


多部件滤波器
org.springframework.web.multipart.support.MultipartFilter
springSecurityFilterChain
org.springframework.web.filter.DelegatingFilterProxy
多部件滤波器
/*
springSecurityFilterChain
/*
将CSRF令牌包括在行动中

如果不允许未经授权的用户上载临时文件,另一种方法是将MultipartFilter放在Spring Security filter之后,并将CSRF作为查询参数包含在表单的action属性中。下面显示了一个jsp示例



这种方法的缺点是查询参数可能泄漏。更一般地说,将敏感数据放在正文或标题中以确保其不泄漏被认为是最佳做法。更多信息可在中找到。

我的快速解决方案如下

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<title>Upload File Request Page</title>
</head>
<body>
    <form method="POST" action="file/uploadFile?${_csrf.parameterName}=${_csrf.token}" enctype="multipart/form-data">
        File to upload: <input type="file" name="file"><br /> 
        Name: <input type="text" name="name"><br /> <br /> 
        <input type="submit" value="Upload"> Press here to upload the file!
    </form> 
</body>
</html>
我在spring dispatcher文件中添加了以下代码

<!-- upload files -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

         <!-- setting maximum upload size -->
        <property name="maxUploadSize" value="100000" />

    </bean>

我的解决方案是在我的
WebSecurityConfig
中禁用
csrf()

 @EnableWebSecurity
 @Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable();
    }
}
现在我可以简单地上传多部分文件:)

即使使用csrf().disable()也不行。 一旦我禁用它,我得到了200,但该文件没有上传,我没有看到任何错误。 一旦我设置了调试标志logging.level.org.springframework.web:debug 我看到了根本原因:

[org.springframework.web.multipart.MultipartException:无法解析多部分servlet请求;嵌套异常为java.io.IOException:临时上载位置[/target/tomcat/work/tomcat/localhost/ROOT]无效],“异常”:“}

我尝试在application.yaml上设置位置: spring.servlet.http.multipart.location:“/tmp” 但是它没有改变位置,所以我添加了下面的代码,它做到了:

@豆子


您是如何配置web.xml的,还是使用WebApplicationInitializer for DispatcherServlet的?您可以发布代码吗?还可以提及您用于加载html表单的url。@Raghu我已经包含了我的WebAppInitializer-我表单的url位于/web-INF/html文件夹中,我的所有Thymeleaf视图都在该文件夹中解析。holmis83我相信是的HanksRob,我已经阅读了Spring文档并尝试了这些方法,但都没有用。我会再试一次,然后再给你回复
<!-- upload files -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

         <!-- setting maximum upload size -->
        <property name="maxUploadSize" value="100000" />

    </bean>
 @EnableWebSecurity
 @Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable();
    }
}
MultipartConfigElement multipartConfigElement() {
    MultipartConfigFactory factory = new MultipartConfigFactory();
    String location = "/tmp";
    LOGGER.debug("Multipart location file:" + location);
    File tmpFile = new File(location);
    if (!tmpFile.exists()) {
        tmpFile.mkdirs();
    }
    factory.setLocation(location);
    return factory.createMultipartConfig();
}