Printemps jeton CSRF ne fonctionne pas, lorsque la demande doit être envoyé est un multipart demande
Que j'utilise,
- Spring Framework VERSION 4.0.0 (GA)
- Printemps de Sécurité VERSION 3.2.0 (GA)
- Struts 2.3.16
Dans lequel, j'utilise un jeton de sécurité pour se prémunir contre les attaques de type CSRF.
Les montants à la forme ressemble à la suivante.
<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>
Le code HTML généré est comme suit.
<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>
Cela fonctionne très bien, sauf si la demande est multipart dans ce cas, la demande se termine avec le code de statut 403.
D'État HTTP 403 - Invalide Jeton CSRF 'null', a été trouvé sur la demande
le paramètre '_csrf' ou l'en-tête "X-CSRF TOKEN'.type rapport de situation
message Invalide Jeton CSRF 'null', a été trouvé sur le paramètre de la requête
'_csrf' ou l'en-tête "X-CSRF TOKEN'.description l'Accès à la ressource spécifiée a été interdit.
La spring-security.xml
fichier est comme suit.
<?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>
Alors, où chercher de ce jeton, lorsqu'une demande est en plusieurs parties? (Cela ne devrait pas être liée à jambes de suspension à tous.)
La mise en œuvre de UserDetailsService
peut être trouvé dans cette plus tôt question de la mienne, si nécessaire.
Plaçant MultipartFilter
avant le Printemps de Sécurité n'a pas aidé non plus.
La web.xml
fichier se présente comme suit.
<?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>
Il fonctionne uniquement lorsque le jeton est ajouté comme une chaîne de requête de paramètre comme suit ce qui est cependant, découragé.
<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>
OriginalL'auteur Tiny | 2014-02-02
Vous devez vous connecter pour publier un commentaire.
Si vous utilisez @annotations, et le jsp vue comme:
cela peut aider:
AppConfig.java :
L'SecurityConfig.java s'étend WebSecurityConfigurerAdapter et est la configuration pour SpringSecurity
Le multipart/form-data filtre (MultipartFilter) doit être enregistré avant la SecurityConfig qui permet à l'CSRF. Vous pouvez le faire avec ceci:
SecurityInitializer.java:
OriginalL'auteur Dominik Minc
Dans ce cas, puisqu'il est un multipart demande dans lequel le jeton CSRF est pas disponible pour le Printemps de sécurité, à moins que
MultipartFilter
avecMultipartResolver
est correctement configuré de sorte que le multipart demande pourra être traitée par le Printemps.MulipartResolver
dans leapplicationContext.xml
fichier doit être enregistré comme suitLa valeur de l'attribut
-1
demaxUploadSize
n'impose aucune limite sur le fichier téléchargé taille. Cette valeur peut varier en fonction des besoins. Dans le cas de plusieurs fichiers, la taille du fichier est de la taille de tous les fichiers téléchargés.Aussi,
de
<filter-mapping>
deMultipartFilter
doit être modifié pourC'est un bug dans le la documentation.
Cela fonctionne très bien, dans ce cas, il est Spring MVC seul.
mais si c'est une intégration de Spring et Struts(2), il engage un autre problème dans les jambes de suspension de l'action de classe. Les informations du fichier téléchargé sera
null
dans les jambes de suspension de l'action de classe(es).Pour résoudre ce problème, reportez-vous cette réponse à personnaliser un multipart demande.
OriginalL'auteur Tiny
J'ai résolu ce problème en:
au lieu de l'aide de jquery, de l'ajouter directement à l'objet XHR
OriginalL'auteur Andrei Epure
Vous pouvez désactiver csrf - httpSecurity.csrf().disable();
OriginalL'auteur AlexSmith