【问题标题】:Token/TokenSession interceptor leading to nullpointer on HttpSession令牌/令牌会话拦截器导致 HttpSession 上的空指针
【发布时间】:2015-07-24 05:23:46
【问题描述】:

我正在开发 struts2 Web 应用程序,我正在使用令牌拦截器处理 CSRF 漏洞。

我所做的是关于成功和错误,我将将用户重定向到同一页面,但带有操作错误或成功消息。

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

没有令牌/令牌会话拦截器一切正常,但是当我使用拦截器时,我得到 NullPointerException。

堆栈跟踪

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]

动作类

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. 代码有什么问题?

  2. 不在同一页面上重定向会导致问题(提交的令牌 会与新生成的令牌不同)?

  3. 如果是,那么我应该如何处理这种情况而不重定向到其他页面?

【问题讨论】:

    标签: java struts2 csrf-protection struts2-interceptors interceptorstack


    【解决方案1】:
    <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>
    

    您正在运行仅令牌拦截器。您需要运行整个堆栈,其中包含令牌拦截器。否则强制拦截器,如 Parameter Interceptor 和 ModelDriven Interceptor(因为您使用的是 ModelDriven)将不会运行,不会设置参数并且您将得到 NullPointerException。将其更改为:

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

    还要注意术语,你不是在重定向任何东西,你只是在调度。重定向意味着一组完全不同的问题,例如参数丢失,并且只发生在redirectredirectAction 结果中。

    【讨论】:

    • 虽然本身没有定义任何拦截器引用的操作将在操作声明自己的拦截器后立即继承默认拦截器,但它会失去自动默认值,并且必须显式命名 defaultStack 才能使用它。所以令牌拦截器不是自己的......那么为什么我们需要定义默认拦截器......??如果我错了,请纠正我:) :P :)
    • 我不确定你在问什么 :D 默认情况下,每个操作都有 defaultStack。如果您定义了一个自定义堆栈,您可以从单个操作中引用它,或者使用 标签将其设置为默认值,它将被每个操作使用。否则,您可以为单个操作指定单个拦截器,甚至堆栈 拦截器。如果您有 99% 的时间使用相同的堆栈,只需将其定义为默认值并处理操作中的异常。如果你有很多异常,定义多个堆栈,并从每个动作不同地引用正确的堆栈......清楚吗?
    • @AndreaLigios 性能方面,token 和 tokenSession 哪个更好?
    • @AndreaLigios 是的,它有效,我会在完成代码测试后立即选择并投票。顺便说一句,你在两天内解决了我的两个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-24
    • 2021-11-12
    • 2020-05-12
    • 2019-07-09
    相关资源
    最近更新 更多