1

I am working on struts2 web application, I am handling CSRF vulnerability by using token interceptor.

what I am doing is on success as well as error, I will be redirecting user to the same page but with action error or success message.

<action name="saveApplicationForm" class="action.ApplicationFormAction" 
      method="saveApplicationForm">
        <interceptor-ref name="token" />
        <result name="invalid.token" type="tiles">applicationForm.tiles</result>    
        <result name="input" type="tiles">applicationForm.tiles</result>
</action>

without token/tokenSession interceptor everything is working fine, but when I am using interceptor I am getting NullPointerException.

stacktrace

java.lang.NullPointerException: null
at action.ApplicationFormAction.saveApplicationForm(ApplicationFormAction.java:218) ~[ApplicationFormAction.class:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_67]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_67]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_67]
at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_67]
at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:450) [xwork-core-2.3.16.3.jar:2.3.16.3]
at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:289) [xwork-core-2.3.16.3.jar:2.3.16.3]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:252) [xwork-core-2.3.16.3.jar:2.3.16.3]
at org.apache.struts2.interceptor.TokenInterceptor.handleValidToken(TokenInterceptor.java:193) [struts2-core-2.3.16.3.jar:2.3.16.3]
at org.apache.struts2.interceptor.TokenInterceptor.handleToken(TokenInterceptor.java:154) [struts2-core-2.3.16.3.jar:2.3.16.3]
at org.apache.struts2.interceptor.TokenInterceptor.doIntercept(TokenInterceptor.java:142) [struts2-core-2.3.16.3.jar:2.3.16.3]
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) [xwork-core-2.3.16.3.jar:2.3.16.3]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246) [xwork-core-2.3.16.3.jar:2.3.16.3]
at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54) [struts2-core-2.3.16.3.jar:2.3.16.3]
at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:562) [struts2-core-2.3.16.3.jar:2.3.16.3]
at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77) [struts2-core-2.3.16.3.jar:2.3.16.3]
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99) [struts2-core-2.3.16.3.jar:2.3.16.3]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.63]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.63]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) [catalina.jar:7.0.63]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) [catalina.jar:7.0.63]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) [catalina.jar:7.0.63]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) [catalina.jar:7.0.63]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) [catalina.jar:7.0.63]
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957) [catalina.jar:7.0.63]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [catalina.jar:7.0.63]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423) [catalina.jar:7.0.63]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079) [tomcat-coyote.jar:7.0.63]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620) [tomcat-coyote.jar:7.0.63]
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318) [tomcat-coyote.jar:7.0.63]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_67]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_67]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-coyote.jar:7.0.63]
at java.lang.Thread.run(Thread.java:745) [na:1.7.0_67]

Action class

public class ApplicationFormAction extends ActionSupport implements ModelDriven<ApplicationFormBean>, SessionAware
{
   private Map<String, Object> session; 
    // getter and setter

   public String saveApplicationForm()
   {
      // getting nullpointer here
     ApplicationFormBean sessApplicationFormBean = (ApplicationFormBean) this.session.get(SESSION_KEY_APPLICANT);
   }

}
  1. what is wrong with the code?

  2. ain't redirecting on same page will cause problem(submitted token will be different from newly generated token)?

  3. if yes then how should I handle this situation without redirecting to other page?
Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
Govinda Sakhare
  • 5,009
  • 6
  • 33
  • 74

1 Answers1

5
<action name="saveApplicationForm" class="action.ApplicationFormAction" 
      method="saveApplicationForm">
        <interceptor-ref name="token" />
        <result name="invalid.token" type="tiles">applicationForm.tiles</result>    
        <result name="input" type="tiles">applicationForm.tiles</result>
</action>

You are running only the Token Interceptor. You need to run an entire stack instead, containing the Token Interceptor. Otherwise mandatory interceptors like Parameter Interceptor and ModelDriven Interceptor (since you're using ModelDriven) won't run, parameters won't be set and you will get NullPointerException. Change it to:

<action name="saveApplicationForm" class="action.ApplicationFormAction"
      method="saveApplicationForm">
        <interceptor-ref name="defaultStack" />
        <interceptor-ref name="token" />
        <result name="invalid.token" type="tiles">applicationForm.tiles</result>    
        <result name="input" type="tiles">applicationForm.tiles</result>
</action>

Also pay attention to the terminology, you are not redirecting anything, you're just dispatching. Redirecting implies a whole different set of problems like lost of parameters, and it happens only with redirect and redirectAction results.

Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
  • while actions that don’t define any interceptor-refs themselves will inherit the default interceptors as soon as an action declares its own interceptors, it loses that automatic default and must explicitly name the defaultStack in order to use it. so token intercepter is not own...then why we need to define default interceptors..?? Correct me if i am wrong :) :P :) – goodyzain Jul 24 '15 at 07:42
  • I'm not sure what you are asking :D By default, you have defaultStack for every action. If you define a custom stack, you can reference it from single actions, or set it as default with tag, and it will be used by every action. Otherwise you can specify single interceptors, or even stacks *and* interceptors, for single actions. If you have 99% of the times the same stack, just define it as default and handle the exceptions in the actions. If you have a lot of exceptions, define multiple stacks and reference the right stack differently from each action... is it clear ? – Andrea Ligios Jul 24 '15 at 07:48
  • @goodyzain see as example: http://stackoverflow.com/a/27702918/1654265 and http://stackoverflow.com/a/27295251/1654265 – Andrea Ligios Jul 24 '15 at 07:53
  • @AndreaLigios performance wise which one is better between token and tokenSession? – Govinda Sakhare Jul 24 '15 at 08:33
  • @piechuckerr in the answer I've linked to you in a previous question ( http://stackoverflow.com/a/28717589/1654265 ) it's clearly highlighted the difference between the two, they **do different things**; 1) token send an error to every request after the first, while 2) tokensession swallows the error and render the first request's result to every request after the first. You must decide which one you do want, no performance comparison can be involved if they do different things :) – Andrea Ligios Jul 24 '15 at 08:57
  • @piechuckerr BTW what about *this* answer ? Did it answer the question, did it work ? – Andrea Ligios Jul 24 '15 at 08:58