1
votes

I have one login page, with a sign-in pop-up, which has username, password and a captcha. Each time when I try to post the form using ajax ( return value is json ), I will get an error like this:

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

and

Form token B4KX7L4ER1FXK5BRJZJ19QTGG4EGRGME does not match the session token null

Login.jsp

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

and inside body tag

<s:token/>

Signin.jsp (Popup for login)

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

What is preventing the token to be correctly passed to the action ?

1

1 Answers

0
votes

You need to exclude the token parameters from the ones intercepted by the Parameters Interceptor.

By default, the 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\...*

By default, the ^struts\..* part of the regex will excldue struts.token and struts.token.name.

You have most likely overriden the default excluded parameters in your Parameters Interceptor, without extending the original excluded ones.

Then:

  1. Manually add the exclusion for the token parameters:

    <interceptor-ref name="params">  
        <param name="excludeParams">
            myStuff\..*,struts.token,struts.token.name
        </param>  
    </interceptor-ref>  
    
  2. or, much better, add your custom exclusion to the original list instead of replacing it:

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

EDIT

After you added the code, I can see some error:

  1. remove myStuff\..*, I put it as a placeholder to your real customization, it's not needed;
  2. put the whole regex in one line, I've splitted it only to improve readability of the answer;
  3. You are setting the param exclusion on a Parameters Interceptor, then importing the whole defaultStack that itself contains another Parameters Interceptor. You should open the defaultStack tag and set the exclusion there (this however doesn't explain the problem because it means you are not overriding the default exclusion...).
  4. Also the FileUpload Interceptor is already in the defaultStack, so you're running it twice.

Then try with:

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

If it doesn't work, try with:

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