无法验证提供的CSRF令牌。仅使用xml

时间:2017-02-20 00:53:42

标签: java spring

我正在学习Spring框架,我使用xml配置文件来保证安全性:

<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>

并以我的登录表单:

<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>

但在我登录并经过一段时间后(我在web.xml中将会话超时设置为1分钟)我在浏览器中收到此错误:

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

到目前为止,我找不到任何仅使用xml文件进行配置的帖子。它完全是关于使用java进行配置,其他一些答案建议在登录表单中包含csrf隐藏输入,我已经这样做了。知道如何解决这个问题吗?

P.S。:web.xml文件如下所示:

<?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>

我将以下配置添加到我的安全配置文件中。

我将此添加到我的security-context.xml,这是一个安全配置文件。

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

我希望令牌在1分钟后有效,持续1209600秒。

3 个答案:

答案 0 :(得分:4)

我不明白这里令人惊讶的部分在哪里?你说那个

  

我在web.xml中将会话超时设置为1分钟

除了会话之外,服务器还可以存储其CSRF令牌的副本吗?因此,当您的会话在一分钟内到期时,服务器无法找到其副本以匹配您的请求中的CSRF令牌并引发此类异常。

我认为您可以查看https://github.com/spring-projects/spring-security/blob/master/web/src/main/java/org/springframework/security/web/csrf/CsrfFilter.java#L113https://github.com/spring-projects/spring-security/blob/master/web/src/main/java/org/springframework/security/web/csrf/HttpSessionCsrfTokenRepository.java#L75

周围的相关代码

因此,只需增加会话超时即可解决问题。 (仅1分钟的超时时间对我来说似乎非常严格。即使在“安全”的地方,我也没有看到现实生活中不到10分钟的任何事情,通常还有更多。)

答案 1 :(得分:0)

这是spring xml配置的整个文件吗?  在启动xml之前,尝试在您提供的xml块的开头添加此块。

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

</security:http>
<security:http auto-config:"true"/>

这使http能够适应防止请求伪造的属性,如果主机的IP地址声明的话。

由于此安全漏洞被引发,将其关闭,将使主机的浏览器不安全,在这种情况下就是您。这样做是正常的,并会取消阻止你。 Althouh我从未见过这个问题

session not found

如果请求伪造被关闭,那么它应该足以识别系统的会话SID。 一旦在xml中添加它,也删除它,您不再需要它作为隐藏参数

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

希望它有所帮助。

答案 2 :(得分:0)

会话过期一分钟后,预计会失败CSRF。在这种情况下,用户需要做的是在登录(或任何非获取)请求之前刷新浏览器。如果用户不这样做,您可以重新加载登录页面,并附上一些非常消息。

为了获得更好的用户体验,如果可能的话,您可以尝试一些基于AJAX的UI技术。