【问题标题】:Unable to match csrf-token using ajax/json无法使用 ajax/json 匹配 csrf-token
【发布时间】:2015-08-10 12:46:36
【问题描述】:

我有一个登录页面,带有一个登录弹出窗口,其中包含用户名、密码和验证码。每次我尝试使用 ajax 发布表单(返回值为 json )时,我都会收到如下错误:

com.opensymphony.xwork2.ognl.OgnlValueStack - 设置表达式 'struts.token.name' 的值为 '[Ljava.lang.String;@53401791' ognl.OgnlException 时出错:getProperty(null, "token") 的源为空

表单令牌 B4KX7L4ER1FXK5BRJZJ19QTGG4EGRGME 与会话令牌 null 不匹配

Login.jsp

<script>
    var strutsToken = "<s:property value="#session['struts.tokens.token']" />";
</script>

和内部标签

<s:token/>

Signin.jsp(登录弹出窗口)

<script>
    var strutsToken = "<s:property value="#session['struts.tokens.token']" />";
</script>

<script>
$(document).ready(function () {

    // For making new captcha image     
    var df = "Captcha?token=" + strutsToken + "&struts.token.name=token";      

    $("#IMA").attr("src", df);   // IMA is id of captcha image    

    $('#mini').click(function () {   // mini is id of submit button

        $.post('Auth', {
            username: document.getElementById('username').value,
            pass: document.getElementById('pass').value,
            Captcha: document.getElementById('Captcha').value,
            token: strutsToken,
            'struts.token.name': "token"
        }, function (jsonResponse) {
            if (jsonResponse.res == "1") {   
                console.log('valid');
                window.location = "campaign/campaign_dashboard.jsp";
            }
            else if (jsonResponse.res == "2") {   
                console.log('valid');
                window.location = "Main.jsp";
            } else {
                $('#result').text(jsonResponse.res);
            }
        }, 'json');
    });
});
</script>

Struts.xml

 <interceptor-stack name="myStack">
            <interceptor-ref name="authenticationInterceptor" >                                      </interceptor-ref>              
            <interceptor-ref name="cachingHeadersInterceptor" />
            <interceptor-ref name="fileUpload" >
            </interceptor-ref>
            <interceptor-ref name="token"></interceptor-ref>
            <interceptor-ref name="params">  
                <param name="params.excludeParams">
        token,dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*
    </param>  
            </interceptor-ref>  
            <interceptor-ref name="defaultStack"/>                                  
        </interceptor-stack>
    </interceptors>
    <default-interceptor-ref name="myStack"/>

是什么阻止了令牌正确传递给操作?

【问题讨论】:

    标签: java jsp struts2 csrf struts2-interceptors


    【解决方案1】:

    您需要从参数拦截器拦截的参数中排除令牌参数。

    默认情况下,Parameters Interceptor already excludes them:

    这个拦截器可以通过设置 excludeParams 属性来强制忽略参数。此属性接受以逗号分隔的正则表达式列表。当这些表达式中的任何一个与参数的名称匹配时,拦截器将忽略该参数。 Struts 定义的拦截器栈已经排除了一些参数:

    默认排除参数列表

    dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,
    ^servlet(Request|Response)\..*,parameters\...*
    

    默认情况下,正则表达式的^struts\..* 部分将排除struts.tokenstruts.token.name

    您很可能已经覆盖了参数拦截器中的默认排除参数,而没有扩展原始排除的参数。

    然后:

    1. 手动添加token参数的排除:

      <interceptor-ref name="params">  
          <param name="excludeParams">
              myStuff\..*,struts.token,struts.token.name
          </param>  
      </interceptor-ref>  
      
    2. 或者,更好将您的自定义排除添加到原始列表中,而不是替换它:

      <interceptor-ref name="params">  
          <param name="excludeParams">
              myStuff\..*,dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,
              ^servlet(Request|Response)\..*,parameters\...*
          </param>  
      </interceptor-ref>  
      

    编辑

    添加代码后,我可以看到一些错误:

    1. 去掉myStuff\..*,我把它作为你真正自定义的占位符,不需要;
    2. 将整个正则表达式放在一行中,我将其拆分只是为了提高答案的可读性;
    3. 您正在对参数拦截器设置参数排除,然后导入本身包含另一个参数拦截器的整个 defaultStack。您应该打开 defaultStack 标记并在那里设置排除项(但这并不能解释问题,因为这意味着您没有覆盖默认排除项......)。
    4. 此外,FileUpload 拦截器已经在 defaultStack 中,因此您需要运行它两次。

    然后尝试:

    <interceptor-stack name="myStack">
        <interceptor-ref name="authenticationInterceptor" />              
        <interceptor-ref name="cachingHeadersInterceptor" />
        <interceptor-ref name="token" />
        <interceptor-ref name="defaultStack" />
    </interceptor-stack>
    

    如果不起作用,请尝试:

    <interceptor-stack name="myStack">
        <interceptor-ref name="authenticationInterceptor" />              
        <interceptor-ref name="cachingHeadersInterceptor" />
        <interceptor-ref name="token" />
        <interceptor-ref name="defaultStack">
            <param name="params.excludeParams">
                token,dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*
            </param>
        </interceptor-ref>
     </interceptor-stack>
    

    【讨论】:

    • 仍然出现同样的异常:org.apache.struts2.util.TokenHelper - 表单令牌 IQTU1POQRNL20PI8Q8DF961SE40E47MN 与会话令牌 null 不匹配。
    • 你确定你已经以正确的方式配置了拦截器,并且你正在使用该拦截器来执行这些操作吗?您可以将您的 struts.xml 添加到问题中吗?
    • 哪个 struts2 版本,顺便说一句?
    • struts 2.3.15 版本
    猜你喜欢
    • 2016-10-09
    • 2016-10-03
    • 2015-08-25
    • 2012-09-12
    • 1970-01-01
    • 1970-01-01
    • 2020-07-06
    • 2022-01-08
    • 2021-12-07
    相关资源
    最近更新 更多