[SPRING] 전송 요청이 다중 요청 인 경우 CSRF 토큰이 작동하지 않습니다.
SPRING전송 요청이 다중 요청 인 경우 CSRF 토큰이 작동하지 않습니다.
나는 사용한다,
CSRF 공격을 막기 위해 내장 된 보안 토큰을 사용합니다.
Struts 형식은 다음과 같습니다.
<s:form namespace="/admin_side"
action="Category"
enctype="multipart/form-data"
method="POST"
validate="true"
id="dataForm"
name="dataForm">
<s:hidden name="%{#attr._csrf.parameterName}"
value="%{#attr._csrf.token}"/>
</s:form>
생성 된 HTML 코드는 다음과 같습니다.
<form id="dataForm"
name="dataForm"
action="/TestStruts/admin_side/Category.action"
method="POST"
enctype="multipart/form-data">
<input type="hidden"
name="_csrf"
value="3748c228-85c6-4c3f-accf-b17d1efba1c5"
id="dataForm__csrf">
</form>
요청이 multipart 인 경우를 제외하고는 제대로 작동하지만 요청은 상태 코드 403과 함께 끝납니다.
spring-security.xml 파일은 다음과 같습니다.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<http pattern="/Login.jsp*" security="none"></http>
<http auto-config='true' use-expressions="true" disable-url-rewriting="true" authentication-manager-ref="authenticationManager">
<session-management session-fixation-protection="newSession">
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
<csrf/>
<headers>
<xss-protection />
<frame-options />
<!--<cache-control />-->
<!--<hsts />-->
<content-type-options /> <!--content sniffing-->
</headers>
<intercept-url pattern="/admin_side/**" access="hasRole('ROLE_ADMIN')" requires-channel="any"/>
<form-login login-page="/admin_login/Login.action" authentication-success-handler-ref="loginSuccessHandler" authentication-failure-handler-ref="authenticationFailureHandler"/>
<logout logout-success-url="/admin_login/Login.action" invalidate-session="true" delete-cookies="JSESSIONID"/>
</http>
<beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<beans:bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="userDetailsService"/>
<beans:property name="passwordEncoder" ref="encoder" />
</beans:bean>
<beans:bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
<beans:property name="providers">
<beans:list>
<beans:ref bean="daoAuthenticationProvider" />
</beans:list>
</beans:property>
</beans:bean>
<authentication-manager>
<authentication-provider user-service-ref="userDetailsService">
</authentication-provider>
</authentication-manager>
<beans:bean id="loginSuccessHandler" class="loginsuccesshandler.LoginSuccessHandler"/>
<beans:bean id="authenticationFailureHandler" class="loginsuccesshandler.AuthenticationFailureHandler" />
<global-method-security secured-annotations="enabled" proxy-target-class="false" authentication-manager-ref="authenticationManager">
<protect-pointcut expression="execution(* admin.dao.*.*(..))" access="ROLE_ADMIN"/>
</global-method-security>
</beans:beans>
그래서,이 토큰을 어디서 찾을 것인가, 요청이 멀티 파트 일 때? (이것은 Struts와 전혀 관련이 없어야합니다.)
UserDetailsService의 구현은 필요한 경우이 이전 질문에서 찾을 수 있습니다.
Spring Security가 도움이되지 않으면 MultipartFilter를 배치하십시오.
web.xml 파일은 다음과 같습니다.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<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>
<servlet-name>/*</servlet-name>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>AdminLoginNocacheFilter</filter-name>
<filter-class>filter.AdminLoginNocacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AdminLoginNocacheFilter</filter-name>
<url-pattern>/admin_login/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>NoCacheFilter</filter-name>
<filter-class>filter.NoCacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<url-pattern>/admin_side/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<description>Description</description>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>struts.devMode</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
다음과 같이 토큰이 쿼리 문자열 매개 변수로 추가 될 때만 작동하지만 이는 권장하지 않습니다.
<s:form namespace="/admin_side"
action="Category?%{#attr._csrf.parameterName}=%{#attr._csrf.token}"
enctype="multipart/form-data"
method="POST"
validate="true"
id="dataForm"
name="dataForm">
...
<s:form>
해결법
-
==============================
1.@annotations를 사용하고 있고 jsp 뷰가 다음과 같은 경우 :
@annotations를 사용하고 있고 jsp 뷰가 다음과 같은 경우 :
<form:form id="profileForm" action="profile?id=${param.id}" method="POST" modelAttribute="appUser" enctype="multipart/form-data" > ... <input type="file" name="file"> ... <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> </form:form>
이 도움이 될 수 있습니다 :
AppConfig.java :
@EnableWebMvc @Configuration @Import({ SecurityConfig.class }) public class AppConfig { @Bean(name = "filterMultipartResolver") public CommonsMultipartResolver filterMultipartResolver() { CommonsMultipartResolver filterMultipartResolver = new CommonsMultipartResolver(); filterMultipartResolver.setDefaultEncoding("utf-8"); // resolver.setMaxUploadSize(512000); return filterMultipartResolver; } ...
SecurityConfig.java는 WebSecurityConfigurerAdapter를 확장하며 SpringSecurity의 구성입니다.
multipart / form-data 필터 (MultipartFilter)는 CSRF를 활성화하는 SecurityConfig보다 먼저 등록해야합니다. 다음과 같이 할 수 있습니다.
SecurityInitializer.java:
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer { @Override protected void beforeSpringSecurityFilterChain(ServletContext servletContext) { super.beforeSpringSecurityFilterChain(servletContext); // CSRF for multipart form data filter: FilterRegistration.Dynamic springMultipartFilter; springMultipartFilter = servletContext.addFilter( "springMultipartFilter", new MultipartFilter()); springMultipartFilter.addMappingForUrlPatterns(null, false, "/*"); } }
-
==============================
2.이 경우, MultipartResolver와 함께 MultipartFilter가 적절히 설정되어 있지 않으면 Spring에서 다중 요청을 처리 할 수없는 한, CSRF 토큰을 Spring 보안에서 사용할 수없는 다중 요청이므로,
이 경우, MultipartResolver와 함께 MultipartFilter가 적절히 설정되어 있지 않으면 Spring에서 다중 요청을 처리 할 수없는 한, CSRF 토큰을 Spring 보안에서 사용할 수없는 다중 요청이므로,
applicationContext.xml 파일의 MulipartResolver는 다음과 같이 등록되어야합니다.
<bean id="filterMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="-1" /> </bean>
maxUploadSize의 속성 값 -1은 업로드 된 파일 크기에 제한을 두지 않습니다. 이 값은 요구 사항에 따라 다를 수 있습니다. 여러 파일의 경우 파일 크기는 업로드 된 모든 파일의 크기입니다.
또한,
<servlet-name>/*</servlet-name>
MultipartFilter의
에 대한 변경 필요 <url-pattern>/*</url-pattern>
이것은 문서의 버그입니다.
이것은 잘 작동 할 것이고, 그럴 경우 Spring MVC 일 뿐이다.
그러나 이것이 Spring과 Struts (2)의 통합 인 경우 관련된 Struts 액션 클래스에서 또 다른 문제가 발생합니다. 업로드 된 파일의 정보는 연관된 Struts 액션 클래스에서 null이 될 것입니다.
이 특정 문제를 해결하려면이 답변을 참조하여 다중 요청을 사용자 정의하십시오.
-
==============================
3.나는이 문제를 다음과 같이 해결했다.
나는이 문제를 다음과 같이 해결했다.
-
==============================
4.csrf-httpSecurity.csrf (). disable ();을 비활성화 할 수 있습니다.
csrf-httpSecurity.csrf (). disable ();을 비활성화 할 수 있습니다.
@Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity httpSecurity) throws Exception { ... httpSecurity.csrf().disable(); ... } }
from https://stackoverflow.com/questions/21514074/spring-csrf-token-does-not-work-when-the-request-to-be-sent-is-a-multipart-requ by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Spring 클래스 경로 접두사 차이 (0) | 2018.12.09 |
---|---|
[SPRING] Spring : 네임 스페이스와 web.xml의 contextConfigLocation 초기화 매개 변수 (0) | 2018.12.09 |
[SPRING] 봄 부팅 REST API - 요청 제한 시간? (0) | 2018.12.09 |
[SPRING] Spring 4.2.3 및 fasterxml Jackson 2.7.0은 호환되지 않습니다. (0) | 2018.12.08 |
[SPRING] Javascript 긴 정수 (0) | 2018.12.08 |