无法验证提供的 CSRF 令牌,因为找不到您的会话

Posted

技术标签:

【中文标题】无法验证提供的 CSRF 令牌,因为找不到您的会话【英文标题】:Could not verify the provided CSRF token because your session was not found 【发布时间】:2016-12-17 14:12:57 【问题描述】:

我一直在寻找这个问题,但仍然无法避免。 只有在我尝试进行 ajax 调用时才会出现问题。系统会返回错误Could not verify the provided CSRF token because your session was not found.

基于Spring MVC and CSRF Integration,如果我使用Java Config,我需要包含@EnableWebSecurity 来解决这个问题,但如果使用XML,则需要使用这个:

@RestController
public class CsrfController 

    @RequestMapping("/csrf")
    public CsrfToken csrf(CsrfToken token) 
        return token;
    

而且我不确定如何使用上面的类。

问题是如何使用上面的类,如果它真的是一个解决方案,或者有什么我可以使用的解决方案?

这是我的安全配置 xml 文件;

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:c="http://www.springframework.org/schema/c"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <!-- Global Security Settings -->
    <global-method-security pre-post-annotations="enabled" />
    <context:component-scan base-package="com.my.web" />

    <!-- Reads WEB Configuration file to resolve $ and read @Value for Security-->
    <context:property-placeholder location="classpath:cfg/web.cfg" />
    <context:annotation-config />

    <!-- Security Access Configuration -->

    <http auto-config="false" use-expressions="true" authentication-manager-ref="CAP" disable-url-rewriting="true" entry-point-ref="IAE">

        <session-management  session-fixation-protection="newSession" session-authentication-error-url="/logout?timeout" >
            <concurrency-control max-sessions="1" expired-url="/logout?expired" />
        </session-management>
        <custom-filter position="PRE_AUTH_FILTER" ref="entryFilter" />
        <intercept-url pattern="/resources/**" access="permitAll()" requires-channel="https" />
        <intercept-url pattern="/clearcache" access="permitAll()" requires-channel="https" />
        <intercept-url pattern="/logout" access="permitAll()" requires-channel="https" />
        <intercept-url pattern="/**" access="isFullyAuthenticated()" requires-channel="https" />

        <port-mappings >
            <port-mapping http="7001" https="7002"  />
        </port-mappings>

    <headers>
        <frame-options policy="SAMEORIGIN" />
        <hsts />
        <cache-control />
        <xss-protection />
        <content-type-options />
    </headers>

    </http>

    <beans:bean id="entryFilter" class="com.my.web.security.HeaderFilter" >
        <beans:property name="authenticationManager" ref="CAP"/>
        </beans:bean>
    <beans:bean id="IAE" class="com.my.web.security.CustomAuthenticationEntryPoint" />
    <beans:bean id="CAP" class="com.my.web.security.CustomAuthenticationManager" />

    <beans:import resource="../aop/aspect-security.xml" />
</beans:beans>

此外,我是一个类似于 CA Siteminder 的使用系统,它将根据标题信息验证用户,而无需登录表单。

【问题讨论】:

AJAX 调用如何指示会话? 是因为 POST 在 ajax 中调用。它需要 csrf 令牌并匹配它将会话令牌 我认为需要提供AJAX调用的代码。 【参考方案1】:

这就是答案!

好的,这件事,从字面上有相同原因的其他问题来看,它主要会影响使用Restheader而没有表单登录的系统。这意味着 webapp 在容器系统中。所以系统或者容器的位置和容器中的系统在客户端的位置是完全不同的。

这里是例子..

对于容器 webapp:

 www.myweb.com/main/

对于容器中的 webapp:

www.myweb.com/main/child

这个不同将拒绝访问并给出 403,因为我们正在寻找的这个肯定不存在。

例子:

www.myweb.com/main/child/playground

/playground uri 存在,但这里肯定是禁止的:

www.myweb.com/main/playground

所以请检查您的 uri 并尝试确保您使用的是相对路径。它要好得多。

P/s:由于某种原因,从服务器端调用的所有内容无论是容器还是容器中的系统都保持不变。这是因为服务器端使用的是相对路径,而不是绝对路径。

【讨论】:

你的例子中主机还是一样的:www.myweb.com,所以应该没有问题。【参考方案2】:

Spring 要求在每次提交表单时发送 csrf 令牌。例如,可以将以下代码插入到 JSP 中:

<form>
[...]
<input type="hidden" name="$_csrf.parameterName" value="$_csrf.token"/> 
[...]
</form>

最好的问候

【讨论】:

【参考方案3】:

我是 SO 新手,这是我的第一个答案,请耐心等待。 这是在使用 jQuery 时进行 AJAX 调用之前必须做的事情:

$(document).ready(

        function() 

            var token = $("meta[name='_csrf']").attr("content");

            $.ajaxSetup(
                headers : 
                    "X-CSRF-Token" : token
                
            );

);

【讨论】:

以上是关于无法验证提供的 CSRF 令牌,因为找不到您的会话的主要内容,如果未能解决你的问题,请参考以下文章

无法验证提供的CSRF令牌,因为找不到您的会话。 拒绝访问 *

使用带有 Spring Security 的 Vaadin 出现 403 CSRF 令牌错误

警告:无法验证 CSRF 令牌的真实性

Laravel CSRF 保护

在 ajax 提交时禁用 symfony 2 csrf 令牌保护

登录、用户身份验证、会话和 csrf 令牌 [关闭]