[SPRING] 업로드 파일 반환 403 오류 - 봄 MVC
SPRING업로드 파일 반환 403 오류 - 봄 MVC
스프링 MVC 프로젝트에서 간단한 폼을 통해 파일을 업로드하려고합니다.
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보기로 리디렉션됩니다.
지금까지 스프링 보안 필터가 별도의 클래스로 초기화되기 전에 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");
}
}
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에 다음을 포함 시키면 아무런 결과도 얻지 못합니다.
.csrf().disable()
해결법
-
==============================
1.이것은 Spring Security 레퍼런스의 CSRF - Multipart (File Upload) 섹션에서 다룹니다. 두 가지 옵션이 있습니다.
이것은 Spring Security 레퍼런스의 CSRF - Multipart (File Upload) 섹션에서 다룹니다. 두 가지 옵션이 있습니다.
스프링 보안 전에 MultipartFilter 배치하기
첫 번째 옵션은 Spring Security 필터 전에 MultipartFilter가 지정되었는지 확인하는 것입니다. Spring Security 필터를 사용하기 전에 MultipartFilter를 지정하면 MultipartFilter를 호출 할 수있는 권한이 없다는 것을 의미합니다. 이는 누군가가 서버에 임시 파일을 배치 할 수 있음을 의미합니다. 그러나 권한이 부여 된 사용자 만 응용 프로그램에서 처리하는 파일을 제출할 수 있습니다. 일반적으로 이것은 임시 파일 업로드가 대부분의 서버에 무시할 수있는 영향을주기 때문에 권장되는 방법입니다.
Java 구성을 사용하는 Spring Security 필터 전에 MultipartFilter가 지정되도록하려면 사용자는 beforeSpringSecurityFilterChain을 다음과 같이 무시할 수 있습니다.
public class SecurityApplicationInitializer extends AbstractSecurityWebApplicationInitializer { @Override protected void beforeSpringSecurityFilterChain(ServletContext servletContext) { insertFilters(servletContext, new MultipartFilter()); } }
XML 구성으로 Spring Security 필터 앞에 MultipartFilter가 지정되도록하기 위해, 사용자는 MultipartFilter의 요소가 web.xml 내의 springSecurityFilterChain 앞에 위치하도록 보장 할 수 있습니다.
<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 토큰 포함
권한이없는 사용자가 임시 파일을 업로드하는 것을 허용 할 수 없다면, Spring Security 필터 다음에 MultipartFilter를 놓고 CSRF를 쿼리 매개 변수로 폼의 action 속성에 포함 시키십시오. jsp를 사용한 예가 아래에 나와 있습니다.
<form action="./upload?${_csrf.parameterName}=${_csrf.token}" method="post" enctype="multipart/form-data">
이 접근법의 단점은 쿼리 매개 변수가 유출 될 수 있다는 것입니다. 더 진부하게, 유출되지 않도록 본문 또는 헤더 내에 중요한 데이터를 배치하는 것이 가장 좋습니다. 추가 정보는 RFC 2616 섹션 15.1.3 URI의 중요한 정보 인코딩에 있습니다.
-
==============================
2.해결책은 WebSecurityConfig에서 csrf ()를 다음과 같이 비활성화하는 것입니다.
해결책은 WebSecurityConfig에서 csrf ()를 다음과 같이 비활성화하는 것입니다.
@EnableWebSecurity @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.cors().and().csrf().disable(); } }
그리고 이제는 간단히 멀티 파트 파일을 업로드 할 수 있습니다. :)
-
==============================
3.나를위한 빠른 해결책은 다음과 같았습니다.
나를위한 빠른 해결책은 다음과 같았습니다.
<%@ 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>
컨트롤러 코드는 다음과 같습니다.
package com.student.controller; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.security.Principal; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; @Controller @RequestMapping("/file") public class FileUploadController { @RequestMapping(value = "", method = RequestMethod.GET) public String index(ModelMap modelMap,Principal principal,HttpServletRequest request) { return "uploadfile"; } @RequestMapping(value = "/uploadFile", method = RequestMethod.POST) public @ResponseBody String uploadFileHandler(@RequestParam("name") String name, @RequestParam("file") MultipartFile file) { if (!file.isEmpty()) { try { byte[] bytes = file.getBytes(); // Creating the directory to store file String rootPath = System.getProperty("catalina.home"); File dir = new File(rootPath + File.separator + "tmpFiles"); if (!dir.exists()) dir.mkdirs(); // Create the file on server File serverFile = new File(dir.getAbsolutePath() + File.separator + name); BufferedOutputStream stream = new BufferedOutputStream( new FileOutputStream(serverFile)); stream.write(bytes); stream.close(); return "You successfully uploaded file=" + rootPath+name; } catch (Exception e) { return "You failed to upload " + name + " => " + e.getMessage(); } } else { return "You failed to upload " + name + " because the file was empty."; } } }
봄 디스패처 파일에 다음 코드를 추가했습니다.
<!-- upload files --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- setting maximum upload size --> <property name="maxUploadSize" value="100000" /> </bean>
from https://stackoverflow.com/questions/32064000/uploading-file-returns-403-error-spring-mvc by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 스프링 부트의 리소스 폴더에서 파일 읽기 (0) | 2019.05.09 |
---|---|
[SPRING] 일치하는 팩토리 메소드가 없습니다. factory 메소드 'aspectOf ()' (0) | 2019.05.09 |
[SPRING] Spring 보안 역할에 기반한 Jackson @JsonIgnore 필드 (0) | 2019.05.09 |
[SPRING] Java 버전 1.7에서 STS를 실행하는 방법 (0) | 2019.05.09 |
[SPRING] Jackson, 참조의 한 속성을 직렬화 (0) | 2019.05.09 |