使用 Struts 的令牌
Use of Token with Struts
当我在我的应用程序中点击 link 两次时出现问题,我完成了 2 个调用并且页面刷新了两次,并且出现了一些错误。
所以我决定使用令牌会话拦截器来防止这个错误。
我正在尝试在我的应用程序中添加 struts 2 tokenSession 拦截器,但我遇到了问题。
我已将此拦截器与所有其他拦截器一起添加:
<interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>
现在,我的动作看起来像:
<action name="SC002AfficherTestSeuil!*" method="{1}" class="fr.edf.mpv2.castor.actions.surveillance.SC002AfficherTestSeuilAction">
<interceptor-ref name="tokenSession"></interceptor-ref>
<interceptor-ref name="mpoStack"></interceptor-ref>
<result name="input">/jsp/fr/edf/mpv2/castor/surveillance/SC002__afficherLesTestsDeSeuil.jsp</result>
<result name="PAGE_SC002_afficherLesTestsDeSeuil">/jsp/fr/edf/mpv2/castor/surveillance/SC002__afficherLesTestsDeSeuil.jsp</result>
</action>
我的页面包含一个列表框和一个按钮名称"show"
当我 select 列表框中的项目时,用户单击显示按钮并完成 ajax 调用。
我进入了public class TokenSessionStoreInterceptor extends TokenInterceptor
的方法
喜欢:
protected String handleInvalidToken(ActionInvocation invocation) throws Exception {
ActionContext ac = invocation.getInvocationContext();
HttpServletRequest request = (HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST);
HttpServletResponse response = (HttpServletResponse) ac.get(ServletActionContext.HTTP_RESPONSE);
String tokenName = TokenHelper.getTokenName();
String token = TokenHelper.getToken(tokenName);
Map params = ac.getParameters();
params.remove(tokenName);
params.remove(TokenHelper.TOKEN_NAME_FIELD);
if ((tokenName != null) && (token != null)) {
ActionInvocation savedInvocation = InvocationSessionStore.loadInvocation(tokenName, token);
if (savedInvocation != null) {
// set the valuestack to the request scope
ValueStack stack = savedInvocation.getStack();
Map context = stack.getContext();
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
ActionContext savedContext = savedInvocation.getInvocationContext();
savedContext.getContextMap().put(ServletActionContext.HTTP_REQUEST, request);
savedContext.getContextMap().put(ServletActionContext.HTTP_RESPONSE, response);
Result result = savedInvocation.getResult();
if ((result != null) && (savedInvocation.getProxy().getExecuteResult())) {
synchronized (context) {
result.execute(savedInvocation);
}
}
// turn off execution of this invocations result
invocation.getProxy().setExecuteResult(false);
return savedInvocation.getResultCode();
}
}
return INVALID_TOKEN_CODE;
}
我不明白为什么,但是这一行 Result result = savedInvocation.getResult();
总是 return 空,所以如果你阅读 struts 代码;我的操作永远不会完成,我的页面也永远不会刷新(记住这是一个 ajax 调用,所以只有一部分页面需要刷新)。
有人可以帮助我理解为什么我的结果为空吗?我是不是忘记配置什么了?
非常感谢
编辑 #1 => 添加 mpoStack
<interceptor-stack name="mpoStack">
<interceptor-ref name="exception" />
<interceptor-ref name="alias" />
<interceptor-ref name="servletConfig" />
<interceptor-ref name="prepare" />
<interceptor-ref name="i18n" />
<interceptor-ref name="chain" />
<!--<interceptor-ref name="debugging" />-->
<!--<interceptor-ref name="profiling" />-->
<!-- Stack d'interceptor sécurité de Marco Polo - Start -->
<interceptor-ref name="securiteStack" >
</interceptor-ref>
<!-- Stack d'interceptor sécurité de Marco Polo - End -->
<interceptor-ref name="fileUpload" />
<interceptor-ref name="checkbox" />
<interceptor-ref name="staticParams" />
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*</param>
</interceptor-ref>
<!--<interceptor-ref name="conversionError" />-->
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse,execute,retour,annuler</param>
</interceptor-ref>
<interceptor-ref name="jsonValidation"/>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse,execute,retour,annuler</param>
</interceptor-ref>
</interceptor-stack>
<interceptor-stack name="mpoStackApplet">
<interceptor-ref name="alias" />
<interceptor-ref name="servletConfig" />
<interceptor-ref name="prepare" />
<interceptor-ref name="chain" />
<interceptor-ref name="securiteStack" />
</interceptor-stack>
<!-- QC#3040 PATROL : web.log : Infinite recursion detected -->
<interceptor-stack name="ErrorStack">
<interceptor-ref name="exception" />
<interceptor-ref name="alias" />
<interceptor-ref name="servletConfig" />
<interceptor-ref name="prepare" />
<interceptor-ref name="i18n" />
<interceptor-ref name="chain" />
<interceptor-ref name="fileUpload" />
<interceptor-ref name="checkbox" />
<interceptor-ref name="staticParams" />
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*</param>
</interceptor-ref>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse,execute,retour,annuler</param>
</interceptor-ref>
<interceptor-ref name="jsonValidation"/>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse,execute,retour,annuler</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="mpoStack" />
看来是 Issue WW-3415 (itself related to Issue WW-3865 and Issue WW-3895).
如果是这种情况,您可以尝试移至 2.3.20,这是第一个已修复该问题的版本。
或者您可以尝试第一期 OP 提出的解决方法,更改
return savedInvocation.getResultCode();
进入
// Checks if the saved invocation has been executed as of now.
// If not it gets executed again.
if(savedInvocation.isExecuted()) {
return savedInvocation.getResultCode();
} else {
return savedInvocation.invoke();
}
最后,问题不是我调用 invalidtoken 的原因,而是像 Roman C 在评论中所说的那样,我此时没有获得有效令牌的原因。所以我已经更正了我的代码来处理有效的令牌,现在一切正常。
当我在我的应用程序中点击 link 两次时出现问题,我完成了 2 个调用并且页面刷新了两次,并且出现了一些错误。
所以我决定使用令牌会话拦截器来防止这个错误。
我正在尝试在我的应用程序中添加 struts 2 tokenSession 拦截器,但我遇到了问题。
我已将此拦截器与所有其他拦截器一起添加:
<interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>
现在,我的动作看起来像:
<action name="SC002AfficherTestSeuil!*" method="{1}" class="fr.edf.mpv2.castor.actions.surveillance.SC002AfficherTestSeuilAction">
<interceptor-ref name="tokenSession"></interceptor-ref>
<interceptor-ref name="mpoStack"></interceptor-ref>
<result name="input">/jsp/fr/edf/mpv2/castor/surveillance/SC002__afficherLesTestsDeSeuil.jsp</result>
<result name="PAGE_SC002_afficherLesTestsDeSeuil">/jsp/fr/edf/mpv2/castor/surveillance/SC002__afficherLesTestsDeSeuil.jsp</result>
</action>
我的页面包含一个列表框和一个按钮名称"show"
当我 select 列表框中的项目时,用户单击显示按钮并完成 ajax 调用。
我进入了public class TokenSessionStoreInterceptor extends TokenInterceptor
喜欢:
protected String handleInvalidToken(ActionInvocation invocation) throws Exception {
ActionContext ac = invocation.getInvocationContext();
HttpServletRequest request = (HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST);
HttpServletResponse response = (HttpServletResponse) ac.get(ServletActionContext.HTTP_RESPONSE);
String tokenName = TokenHelper.getTokenName();
String token = TokenHelper.getToken(tokenName);
Map params = ac.getParameters();
params.remove(tokenName);
params.remove(TokenHelper.TOKEN_NAME_FIELD);
if ((tokenName != null) && (token != null)) {
ActionInvocation savedInvocation = InvocationSessionStore.loadInvocation(tokenName, token);
if (savedInvocation != null) {
// set the valuestack to the request scope
ValueStack stack = savedInvocation.getStack();
Map context = stack.getContext();
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
ActionContext savedContext = savedInvocation.getInvocationContext();
savedContext.getContextMap().put(ServletActionContext.HTTP_REQUEST, request);
savedContext.getContextMap().put(ServletActionContext.HTTP_RESPONSE, response);
Result result = savedInvocation.getResult();
if ((result != null) && (savedInvocation.getProxy().getExecuteResult())) {
synchronized (context) {
result.execute(savedInvocation);
}
}
// turn off execution of this invocations result
invocation.getProxy().setExecuteResult(false);
return savedInvocation.getResultCode();
}
}
return INVALID_TOKEN_CODE;
}
我不明白为什么,但是这一行 Result result = savedInvocation.getResult();
总是 return 空,所以如果你阅读 struts 代码;我的操作永远不会完成,我的页面也永远不会刷新(记住这是一个 ajax 调用,所以只有一部分页面需要刷新)。
有人可以帮助我理解为什么我的结果为空吗?我是不是忘记配置什么了?
非常感谢
编辑 #1 => 添加 mpoStack
<interceptor-stack name="mpoStack">
<interceptor-ref name="exception" />
<interceptor-ref name="alias" />
<interceptor-ref name="servletConfig" />
<interceptor-ref name="prepare" />
<interceptor-ref name="i18n" />
<interceptor-ref name="chain" />
<!--<interceptor-ref name="debugging" />-->
<!--<interceptor-ref name="profiling" />-->
<!-- Stack d'interceptor sécurité de Marco Polo - Start -->
<interceptor-ref name="securiteStack" >
</interceptor-ref>
<!-- Stack d'interceptor sécurité de Marco Polo - End -->
<interceptor-ref name="fileUpload" />
<interceptor-ref name="checkbox" />
<interceptor-ref name="staticParams" />
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*</param>
</interceptor-ref>
<!--<interceptor-ref name="conversionError" />-->
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse,execute,retour,annuler</param>
</interceptor-ref>
<interceptor-ref name="jsonValidation"/>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse,execute,retour,annuler</param>
</interceptor-ref>
</interceptor-stack>
<interceptor-stack name="mpoStackApplet">
<interceptor-ref name="alias" />
<interceptor-ref name="servletConfig" />
<interceptor-ref name="prepare" />
<interceptor-ref name="chain" />
<interceptor-ref name="securiteStack" />
</interceptor-stack>
<!-- QC#3040 PATROL : web.log : Infinite recursion detected -->
<interceptor-stack name="ErrorStack">
<interceptor-ref name="exception" />
<interceptor-ref name="alias" />
<interceptor-ref name="servletConfig" />
<interceptor-ref name="prepare" />
<interceptor-ref name="i18n" />
<interceptor-ref name="chain" />
<interceptor-ref name="fileUpload" />
<interceptor-ref name="checkbox" />
<interceptor-ref name="staticParams" />
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*</param>
</interceptor-ref>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse,execute,retour,annuler</param>
</interceptor-ref>
<interceptor-ref name="jsonValidation"/>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse,execute,retour,annuler</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="mpoStack" />
看来是 Issue WW-3415 (itself related to Issue WW-3865 and Issue WW-3895).
如果是这种情况,您可以尝试移至 2.3.20,这是第一个已修复该问题的版本。
或者您可以尝试第一期 OP 提出的解决方法,更改
return savedInvocation.getResultCode();
进入
// Checks if the saved invocation has been executed as of now.
// If not it gets executed again.
if(savedInvocation.isExecuted()) {
return savedInvocation.getResultCode();
} else {
return savedInvocation.invoke();
}
最后,问题不是我调用 invalidtoken 的原因,而是像 Roman C 在评论中所说的那样,我此时没有获得有效令牌的原因。所以我已经更正了我的代码来处理有效的令牌,现在一切正常。