Failed to verify the provided CSRF token. Using only xml

I am studying Spring framework and I am using xml configuration file for security:

<security:http once-per-request="false" use-expressions="true"> <!-- <security:intercept-url pattern="/admin" access="hasAuthority('ROLE_ADMIN')" /> --> <security:intercept-url pattern="/admin" access="permitAll" /> <security:intercept-url pattern="/createoffer" access="isAuthenticated()" /> <security:intercept-url pattern="/docreateoffer" access="isAuthenticated()" /> <security:intercept-url pattern="/offercreated" access="isAuthenticated()" /> <security:intercept-url pattern="/" access="permitAll" /> <security:intercept-url pattern="/denied" access="permitAll" /> <security:intercept-url pattern="/loggedout" access="permitAll" /> <security:intercept-url pattern="/newaccount" access="permitAll" /> <security:intercept-url pattern="/createaccount" access="permitAll" /> <security:intercept-url pattern="/accountcreated" access="permitAll" /> <security:intercept-url pattern="/static/**" access="permitAll" /> <security:intercept-url pattern="/login" access="permitAll" /> <security:intercept-url pattern="/offers" access="permitAll" /> <security:intercept-url pattern="/**" access="denyAll" /> <security:form-login login-page="/login" authentication-failure-url="/login?error=true" /> <security:logout logout-success-url="/loggedout" logout-url="/logout"/> <security:remember-me key="offersAppKey" user-service-ref="jdbcUserService" remember-me-parameter="remember-me" token-validity-seconds="1209600" /> </security:http> 

and in my login form:

 <form name='f' action='${pageContext.request.contextPath}/login' method='POST'> <table> <tr> <td>User:</td> <td><input type='text' name='username' value=''></td> </tr> <tr> <td>Password:</td> <td><input type='password' name='password' /></td> </tr> <tr> <td>Remember Me</td> <td><input type="checkbox" checked="checked" name="remember-me" /></td> </tr> <tr> <td colspan='2'><input name="submit" type="submit" value="Login" /></td> </tr> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> </table> </form> 

But after I log in and pass for a while (I set the session timeout to 1 minute in web.xml ), I get this error in the browser:

Could not verify the provided CSRF token because your session was not found.

So far, I could not find a message that uses only the xml file for configuration. Everything about tuning using java and some other answers suggests that include csrf hidden input in the login form that I already do. Any idea how to solve this problem?

PS: the web.xml file looks like this:

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>spring-tutorial-51</display-name> <description>Spring tutorial web app</description> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <servlet> <description></description> <display-name>offers</display-name> <servlet-name>offers</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>offers</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <resource-ref> <description>DB Connection</description> <res-ref-name>jdbc/springtutorial</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:com/myproject/spring/web/config/dao-context.xml classpath:com/myproject/spring/web/config/service-context.xml classpath:com/myproject/spring/web/config/security-context.xml </param-value> </context-param> <filter> <display-name>springSecurityFilterChain</display-name> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <session-config> <session-timeout>1</session-timeout> </session-config> </web-app>

I added the following configuration to the security configuration file.

I added this to my security-context.xml , which is a security configuration file.

 <security:remember-me key="offersAppKey" user-service-ref="jdbcUserService" remember-me-parameter="remember-me" token-validity-seconds="1209600" /> 

And I expect the token will be valid in 1 minute in 1209600 seconds.

+5
source share
3 answers

I don’t understand where is this amazing part? you said, that

I set the session timeout to 1 minute in the web.xml file

Where else can the server store its copy of your CSRF token other than your session? Therefore, when your session expires in a minute, the server cannot find its copy in accordance with the CSRF token in your request and raises such an exception.

I think you can see the corresponding code https://github.com/spring-projects/spring-security/blob/master/web/src/main/java/org/springframework/security/web/csrf/CsrfFilter.java# L113 and https://github.com/spring-projects/spring-security/blob/master/web/src/main/java/org/springframework/security/web/csrf/HttpSessionCsrfTokenRepository.java#L75

So, to fix the problem, just increase the session timeout . (The timeout of only 1 minute seems incredibly strict to me. I have not seen anything in my life for less than 10 minutes, even in β€œsafe” places and, as a rule, much more.)

+4
source

Is this your entire spring xml configuration file? Before starting xml, try adding this block at the beginning of your xml block that you provided.

 <security:http csrf disabled="true"> <security:intercept-url pattern="/*" access="ROLE_USER" /> <security:form-login/> </security:http> <security:http auto-config:"true"/> 

This allows http to adapt the request forgery prevention property if someone claims their host IP.

Since this security vulnerability is increased by disabling it, it will be unsafe from the host browser, which in this case is you. Do it normally and unlock. Althouh i never saw a problem

 session not found 

If request fake is disabled, it should be good enough to recognize the session SID for the system. Also remove this by adding this to xml, you will no longer need the hidden parameter

  <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> 

Hope this helps.

0
source

One minute after the end of the session, the CSRF is expected to complete the failure. What the user needs to do in this case is to update the browser before clicking on the login (or any request). And if the user does not, you can reload the login page with some message frieldly.

For better user convenience, you can try some AJAX-based user interfaces if possible ..

0
source

Source: https://habr.com/ru/post/1264428/


All Articles