上传文件返回 403 错误 - Spring MVC [英] Uploading File Returns 403 Error - Spring MVC

查看:50
本文介绍了上传文件返回 403 错误 - Spring MVC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In my Spring MVC project I am trying to upload a file via a simple form.

HTML 表单:

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

我的控制器:

@Controller
public class FileController {
    @RequestMapping(value="/upload", method=RequestMethod.POST)
        public @ResponseBody String handleFileUpload(
                @RequestParam("name") String name,
                @RequestParam("file") MultipartFile file){
            if (!file.isEmpty()) {
                try {
                    //do stuff
                } catch (Exception e) {
                    return "You failed to upload " + name + " => " + e.getMessage();
                }
            } else {
                return "You failed to upload " + name + " because the file was empty.";
            }
        }
}

安全配置:

@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 视图

However I get a 403: Forbidden error and am redirected to my 403.html view every time

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

So far I've tried specifying the MultipartFilter before the Spring Security filter is initialized in a separate class, but no luck

public class SecurityApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

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

有什么想法吗?

更新:包括我的 WebAppInitializer

UPDATE: Including my 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 错误:

I have a list of servlet request attributes that returns the following with the 403 error:

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

Update #2: This is surely a CSRF issue; when I include the following in my WebSecurityConfig I get no 403

.csrf().disable()

推荐答案

这在 CSRF - Multipart (File Upload) 部分.您有两个选择:

This is covered in the CSRF - Multipart (File Upload) section of the Spring Security reference. You have two options:

在 Spring Security 之前放置 MultipartFilter

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

The first option is to ensure that the MultipartFilter is specified before the Spring Security filter. Specifying the MultipartFilter before the Spring Security filter means that there is no authorization for invoking the MultipartFilter which means anyone can place temporary files on your server. However, only authorized users will be able to submit a File that is processed by your application. In general, this is the recommended approach because the temporary file upload should have a negligble impact on most servers.

为确保在 Spring Security 过滤器之前使用 java 配置指定 MultipartFilter,用户可以覆盖 beforeSpringSecurityFilterChain,如下所示:

To ensure MultipartFilter is specified before the Spring Security filter with java configuration, users can override beforeSpringSecurityFilterChain as shown below:

public class SecurityApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

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

为确保在带有 XML 配置的 Spring Security 过滤器之前指定 MultipartFilter,用户可以确保 MultipartFilter 的元素放置在 web.xml 中的 springSecurityFilterChain 之前,如下所示:

To ensure MultipartFilter is specified before the Spring Security filter with XML configuration, users can ensure the element of the MultipartFilter is placed before the springSecurityFilterChain within the web.xml as shown below:

<filter>
    <filter-name>MultipartFilter</filter-name>
    <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>MultipartFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

在操作中包含 CSRF 令牌

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

If allowing unauthorized users to upload temporariy files is not acceptable, an alternative is to place the MultipartFilter after the Spring Security filter and include the CSRF as a query parameter in the action attribute of the form. An example with a jsp is shown below

<form action="./upload?${_csrf.parameterName}=${_csrf.token}" 
      method="post" 
      enctype="multipart/form-data">

这种方法的缺点是查询参数可能会泄露.更一般地说,将敏感数据放在正文或标题中以确保它不会泄露被认为是最佳实践.其他信息可以在 RFC 2616 第 15.1.3 节在 URI 中编码敏感信息.

The disadvantage to this approach is that query parameters can be leaked. More genearlly, it is considered best practice to place sensitive data within the body or headers to ensure it is not leaked. Additional information can be found in RFC 2616 Section 15.1.3 Encoding Sensitive Information in URI’s.

这篇关于上传文件返回 403 错误 - Spring MVC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆