无法使用ajax / json匹配csrf-token

时间:2015-08-07 06:44:03

标签: java jsp struts2 csrf struts2-interceptors

我有一个登录页面,带有登录弹出窗口,其中包含用户名,密码和验证码。每次当我尝试使用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"/>

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

1 个答案:

答案 0 :(得分:0)

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

默认情况下,Parameters Interceptor already excludes them

  

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

     

排除的默认参数列表

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

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

您很可能会覆盖参数拦截器中的默认排除参数,而不会扩展原始排除参数。

然后:

  1. 手动添加令牌参数的排除项:

    <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>  
    
  3. 修改

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

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

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