我正在学习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秒。
答案 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#L113和https://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技术。