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


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





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


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


是什么导致令牌无法正确传递给操作?

最佳答案

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

默认情况下,Parameters Interceptor already excludes them


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

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



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

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

然后:


手动添加标记参数的排除项:

<interceptor-ref name="params">
    <param name="excludeParams">
        myStuff\..*,struts.token,struts.token.name
    </param>
</interceptor-ref>

或者,更好的是,将自定义排除项添加到原始列表中,而不是替换它:

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





编辑

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


删除myStuff\..*,我将其用作您真正的自定义的占位符,不需要它;
将整个正则表达式放在一行中,我将其拆分只是为了提高答案的可读性;
您要在参数拦截器上设置参数排除,然后导入本身包含另一个参数拦截器的整个defaultStack。您应该打开defaultStack标记并在此处设置排除项(但是这不能解释问题,因为这意味着您不会覆盖默认排除项...)。
而且FileUpload Interceptor已经在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>

关于java - 无法使用ajax/json匹配csrf token ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31871276/

10-13 09:12