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

标签 java jsp struts2 csrf struts2-interceptors

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

com.opensymphony.xwork2.ognl.OgnlValueStack - Error setting expression 'struts.token.name' with value '[Ljava.lang.String;@53401791' ognl.OgnlException: source is null for getProperty(null, "token")

Form token B4KX7L4ER1FXK5BRJZJ19QTGG4EGRGME does not match the session token 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"/>

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

最佳答案

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

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

This interceptor can be forced to ignore parameters, by setting its excludeParams attribute. This attribute accepts a comma separated list of regular expressions. When any of these expressions match the name of a parameter, such parameter will be ignored by the interceptor. Interceptor stacks defined by Struts already exclude some parameters:

Default List of Parameters Excluded

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>

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

相关文章:

jsp - Shiro 还在寻找 login.jsp,当所有的应用页面都重命名为 .html

javascript - 通过 JQuery/JS 使用其他组合框选择更新组合框

java --version 显示 10 但已安装 java 11

JavaX 命名.NameNotFoundException 与 Jboss/Wildfly,这个名字是什么意思?

java - 如何将 File.setReadable 映射到 NIO Path 操作

java - 我可以在没有 Spring IoC 的情况下使用 Struts2 吗?

java - URL 重写后所有操作都转发到 Struts2 servlet

java - 类型无法实例化类型 Employee Company.java

linux - 在 Linux 中,log4j.appender.R.File 的默认根目录在哪里?

javascript - 如何将参数从 JSP 传递到 Struts 2 操作